Reputation: 53
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 i.e. 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!
Upvotes: 1
Views: 1444
Reputation: 10242
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
}
}
}
}
`;
Upvotes: 1