An expressive query engine for Cloud Firestore, inspired by GraphQL.
This is not an official Google product, nor is it maintained or supported by Google employees. For support with Firebase or Firestore, please click here.
Introduction
Cloud Firestore is a NoSQL document database built for automatic scaling, high performance, and ease of application development. While the Cloud Firestore interface has many of the same features as traditional databases, as a NoSQL database it differs from them in the way it describes relationships between data objects. It is a part of the Google Cloud platform, and a spiritual successor to the Firebase Real-Time Database.
Firestore makes it easy to securely store and retrieve data, and already has a powerful API for querying data. Firequery builds on that awesome foundation by making it even easier to retrieve data across collections, subcollections, and document references.
Getting Started
Installation
Firequery is available on npm.
npm install --save firequery # or for Yarn: yarn add firequery
After that, you can use it anywhere in your project:
const firequery = require(`firequery`)
firequery.query(db /* Firestore instance */, someQuery)
Usage
The Firequery API is very small; in fact, it only contains one function: resolve
. This function takes two parameters:
- A Firestore instance
- The query you want to run against it
Motivating Example
Suppose you have defined a Firestore collection called posts
, where each post
a structure like so:
{
text: String,
createdAt: Timestamp, // Firestore timestamp instance
author: DocumentReference // Firestore reference instance
}
Per Firestore documentation, if you wanted to retrieve all of this data, you could do something like:
firestore.collection(`posts`).get().then(postsSnapshot => {
posts.forEach(post => {
let data = post.data()
let authorData = data["author"].get().then(authorSnapshot => {
// Finally, we can do something with our post and author data.
})
})
}).catch(err => {
throw new Error(`Error retrieving posts.`)
})
This is pretty straightforward, but what if you have a lot of these references? For some post, what if you want to get additional posts by that same author? Eventually the overhead of all this asynchronous code will catch up with you (pun intended?).
Let's see how that same request can be done with Firequery:
// Specify the data we want
let postsWithAuthors = `
collection {
posts {
text
createdAt
author {
name
photo
}
}
}
`
// Then, with just one line, we get it
let result = firequery.resolve(db /* Firestore instance */, postsWithAuthors)
Roadmap
Right now, we have a pretty basic implementation that resolves collections and documents with support for DocumentReferences. We have a lot of work to do.
- [ ] Integrating
where
,orderBy
,limit
clauses and others. - [ ] Adding support for subcollections.
- [ ] Adding support for real-time updates.
- [ ] TypeScript, a build system, tests, etc.
Contributing
Contributions are welcome and encouraged, either in the form of Issues or Pull Requests. To get started, just clone this repository.
Getting the code
Once you download firequery
, you will want to install its dependencies.
# If you use NPM
npm install
# If you use Yarn
yarn
Running tests
Firequery employs a test-driven development process, meaning that tests should be written first to describe expected/desired behavior, then the source code should be modified to make that test pass. To run our test suite:
# If you use NPM
npm run test
# If you use Yarn
yarn test
If you make a pull request and any of the existing tests fail, as you might imagine, your PR will be rejected.
Linting and type checking
You will see pretty quickly that Firequery is being built with TypeScript. That said, your code will also have to pass tests relating to syntax and typing. You can verify these requirements are met by using additional package scripts:
# If you use NPM
npm run type-check
npm run lint
# If you use Yarn
yarn type-check
yarn lint
Building and bundling
- Building is the process in which we take our TypeScript code and turn it into regular JavaScript that can be imported into any NodeJS project.
- Bundling is the process in which we take our TypeScript code and turn it into a single, minified file that is suitable for inserting in HTML documents.
We have two scripts that handle this for us:
# If you use NPM
npm run build
npm run bundle
# If you use Yarn
yarn build
yarn bundle
Ultimately, when you want to submit a pull request, all of the above scripts should run without any issues.