Firebase & GraphQL [closed]
Solution 1:
To answer your question, there are three ways you can deal with this.
1. Firebase & GraphQL
If you're set on using Firebase, you can make a one-to-one mapping of Firebase's API into GraphQL queries and mutations.
You can surely wrap the Firebase API into GraphQL resolvers, and make calls that way. This is a good example of that:
const ref = path => firebase.database().ref(path)
const getValue = path => ref(path).once('value')
const mapSnapshotToEntities = snapshot => snapshot.val().map((value, id) => ({ id, ...value }))
const getEntities = path => getValue(path).then(mapSnapshotToEntities)
const resolvers = {
Author: {
posts(author) {
return getEntities('posts').then(posts => filter(posts, { authorId: author.id }))
},
},
Post: {
author(post) {
return getEntities('authors').then(posts => filter(authors, { id: authorId }))
},
},
};
Essentially, what you're doing here is using Firebase as a database, which works until you want to query your data in a relational manner in your resolvers. Without the ability to perform joins on the server side on top of your data store, you'll be making tons of round-trip requests to Firebase in your resolvers to fulfill just a single request.
The reason most people use Firebase is for its real-time capabilities, and not primarily just as a data store since the data relational modeling tools in this aspect are fairly lacking. With that, you're probably better off migrating over to GraphQL using a different data source.
2. GraphQL Backend as a Service
Considering you're open to using BaaS products like Firebase, you might consider switching over to a GraphQL BaaS.
3. Self-hosted GraphQL
If you're open to changing over to a self-hosted solution using your own data store, there are many benefits to that as well. Here are a few big hitters:
Flexibility of using your own data store and perhaps multiple to suit your specific app's needs
Custom queries and mutations
Natively add custom logic instead of via microservices attached to webhooks in your API
Roll your own authentication and permissioning mechanisms
Likely a lower-cost solution
Solution 2:
I strongly disagree with some recommendations here. GraphQL can be used in a relational way but it can also be used in a NoSQL way. Firebase, with its RTD (Real Time Database) and Firestore, should be modeled as a NoSQL database because it's a NoSQL database! There are tradeoffs to this approach:
1. Optimized read:
As a NoSQL database, the collections should be modeled as your views in your clients (mobile or web), so when you make a query, everything is already merged and you don't have to make computed props in the client nor Firebase functions. This approach makes reading really REALLY fast.
2. De-optimized write:
The main trade off here is that is your responsibility to update every document in the database if you touch related data (like updating the username, profile picture, etc). In this case you should find every document in your database (ie: posts, comments, etc) and ensure atomicity. This approach is recommended if you have an app that is going to have far more read operations than write operations (like a blog, 7000 reads to 1 write as an example).
3. Easy to scale:
As your collections do not have hard relationships with other documents, you can have a complete collection in only one server or split it among many of them. (That's why Firebase is cheap to scale, like DynamoDB.)
GraphQL is only a query language. It should make easy for you to query things, but it should not dictate how you model your database. You should dictate how to model your database, your queries, and mutations.