简体   繁体   中英

How to query relational data with GraphQL, Firebase and Gatsby

I'm building a Gatsby.js site.

The site uses the gatsby-source-firestore plugin to connect to the Firestore data source.

My question is this. How can I query relational data? As in, fetch data from two models at once, where modelA[x] = modelB[y]

I don't really understand resolvers. I don't think I have any.

Note, I am not considering graph.cool currently. I'd like to stick with Firebase. I will do the relational data matching in pure JS if I have to (not GraphQL).

Here is what my gatsby-config.js looks like:

{
  resolve: 'gatsby-source-firestore',
  options: {
    credential: require('./firebase-key.json'),
    databaseURL: 'https://testblahblah.firebaseio.com',
    types: [
      {
        type: 'Users',
        collection: 'users',
        map: user => ({
          firstName: user.firstName,
          lastName: user.lastName,
          email: user.email,
          ownsHat: user.ownsHat,
          hatId: user.hatId
        })
      },
      {
        type: 'Hats',
        collection: 'hats',
        map: hat => ({
            hatType: hat.hatType,
            hatUserId: hat.hatUserId,
            hatId: hat.hatId
        })
      }
    ]
  }
},

This pulls in two flat data models. I can query like this in-page:

any-page.js

export const query = graphql`
  query {
    allUsers {
      edges {
        node {
          ...UserFragment
        }
      }
    }
  }
`

What I'm looking for is a query that lets me write one query inside another ie a relational data query within a query.

export const query = graphql`
  query {
    allUsers {
      edges {
        node {
          ...UserFragment {
              hats (user.userId == hat.userId){
                  type
                  hatId
              }
          }
        }
      }
    }
  }
`

As you can understand, this amounts to: How to run multiple GraphQL queries of relational data.

Given the nature of Firestore's flat JSON, this makes the relational aspect of GraphQL difficult.

I'm really keen to understand this better and would really appreciate being pointed down the right path.

I am really keen on sticking with GraphQL and Firebase.

Thanks!

I'm not sure this works in graphql but in Gatsby you can use gatsby-node to create and alter your nodes and inject hats to each user node. Here's an example code I'm using to add authors to a Post node:

const mapAuthorsToPostNode = (node, getNodes) => {
    const author = getPostAuthorNode(node, getNodes);
    if (author) node.authors___NODES = [author.id];
};

exports.sourceNodes = ({actions, getNodes, getNode}) => {
    const {createNodeField} = actions;

    getCollectionNodes('posts', getNodes).forEach(node => {
        mapAuthorsToPostNode(node, getNodes);
    });
};

This is one way to do it provided the records are not in huge numbers. If they are, you should create a hats page to display user hats where you query just the hats filtered by user id which is received via a paceContext param such as user id.

export const pageQuery = graphql`
    query($userId: String) {
        hats: allHats(
            filter: {
                userId: {eq: $userId}
            }
        ) {
            edges {
                node {
                    ...hatFragment
                }
            }
        }
    }
`;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM