-
Notifications
You must be signed in to change notification settings - Fork 1
FiremanQL
A FiremanQL query in its basic form is a forward slash separated path string, like the one used to access a Firebase Realtime Database location.
The following query will return the value of baz
, being it a valid node in the Realtime or a document/collection in Firestore:
foo/bar/baz
Identifiers are used to reference nodes, documents, collections or fields inside of documents' data.
They can't contain the following characters: /
, {
, }
, [
, ]
, ,
, ^
, _
, =
, <
, >
and whitespaces. All of those characters except the forward slash can be used if the identifier is surrounded by single or double quotes:
foo/"b,a{r}"/['b^a_z' == 2]
Collection expressions can be included in the path, in place of the document ids, enclosed in square brackets.
They can contain clauses like where, order by etc. depending on the target database.
foo/bar/[ /* Expression */ ]
The where clause has the following shape:
<identifier> <operator> <value>
<identifier>
is a valid Firestore data key identifier.
<operator>
is one of ==, <, >, <=, >=, != (self-explanatory) and has
, which corresponds to Firestore's array_contains
.
<value>
is either a single or double quoted string, a number, true
, false
, or null
.
The order by clause has the following shape:
<direction> <identifier>
Order by clauses consist of a symbol indicating the order direction (^
for ascending, _
for descending) followed by the identifier of the field used for ordering.
The limit clause has the following shape:
# <number>
To limit the number of documents/nodes retrieved one limit clause can be inserted in a collection expression: just type hashtag followed by the number of items.
Document expressions can be used to restrict the queried documents/nodes to certain fields.
foo/bar/{ /* Document expression */ }
A document expression is a comma-separated list of valid document field keys surrounded in curly braces (like in JS destructuring declarations).
Consider the example data from Firestore's documentation:
{
cities: { // Collection
SF: { // Document
name: 'San Francisco',
state: 'CA',
country: 'USA',
capital: false,
population: 860000,
regions: ['west_coast', 'norcal'],
},
LA: {
name: 'Los Angeles',
state: 'CA',
country: 'USA',
capital: false,
population: 3900000,
regions: ['west_coast', 'socal']
},
DC: {
name: 'Washington, D.C.',
state: null,
country: 'USA',
capital: true,
population: 680000,
regions: ['east_coast'],
},
TOK: {
name: 'Tokyo',
state: null,
country: 'Japan',
capital: true,
population: 9000000,
regions: ['kanto', 'honshu'],
},
BJ: {
name: 'Beijing',
state: null,
country: 'China',
capital: true,
population: 21500000,
regions: ['jingjinji', 'hebei'],
},
},
}
The following query returns all cities with state CA:
cities/[state == 'CA']
The following query returns all the capital cities:
cities/[capital == true]
Other filters:
cities/[population < 1000000]
cities/[name >= 'San Francisco']
To filter based on array membership the has
operator can be used:
cities/[regions has 'west_coast']
More where conditions can be chained with commas:
cities/[state == 'CO', name == 'Denver']
be sure to check the limitations on compound queries in the official documentation
Use document expressions to restrict the document keys:
cities/[state == 'CO', name == 'Denver']/{name, population}
And order them:
cities/[^population, state == 'CO', name == 'Denver']/{name, population}
Nested queries can be performed by using more than one collection expression in the path.
The following query selects all family members with a name lexicographically grater than B that live in houses with more than 3 floors:
houses/[floors >= 3]/family/[name >= 'B']
The *
wildcard can also be used to select all documents:
houses/*/family/*
selects all the family members in all houses.
⚠️ Use carefully! This can be particularly expensive in terms of Firebase read quotas.