Skip to content

FiremanQL

Umberto Pepato edited this page Dec 11, 2018 · 6 revisions

FiremanQL syntax

Base structure

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

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

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 */ ]

Where (Firestore only)

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.

Order by

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.

Limit

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

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).

Examples

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'],
    },
  },
}

Simple queries

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']

Compound queries

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

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.