Skip to main content
Version: 1.0 RC1 (Latest)

Filter documents

It's fantastic to be able to store thousands of documents, but all this would be a silly business if you couldn't filter through them, wouldn't it? The filter object allow you to specify criterias for selecting documents. You can filter on:

Display database setup

This page assumes your database contains Book and Person collections and some documents in them:

Database schema
type Person {
name: String!
authoredBooks: [Book]
}

type Book {
title: String!
genre: String
plot: String
rating: Float
author: Person
ratings: [Float]
}
Person documents setup
mutation {
a1:add_Person(input: {
name: "George Orwell"
}) { _docID }
a2:add_Person(input: {
name: "William Golding"
}) { _docID }
a3:add_Person(input: {
name: "David Foster Wallace"
}) { _docID }
a4:add_Person(input: {
name: "Victor Hugo"
}) { _docID }
}
Book documents setup
mutation {
b11:add_Book(input: {
title: "1984",
genre: "Fiction",
plot: "A masterpiece of rebellion and imprisonment where war is peace, freedom is slavery, and Big Brother is watching.",
rating: 4.20,
ratings: [3.8, 4.91, 3.1, 2.8],
_authorID: "bae-3517d1eb-351b-5231-8387-870893ffb395"
}) {
_docID
title
}
b12:add_Book(input: {
title: "Down and Out in Paris and London",
genre: "Biography",
plot: "The adventures of a penniless British writer among the down-and-outs of two great cities.",
rating: 4.09,
_authorID: "bae-3517d1eb-351b-5231-8387-870893ffb395"
}) {
_docID
title
}
b21:add_Book(input: {
title: "Lord of the Flies",
genre: "Fiction",
plot: "At the dawn of the next world war, a plane crashes on an uncharted island, stranding a group of schoolboys.",
rating: 3.70,
_authorID: "bae-78e9c7be-10b9-5673-bad2-da3341367d4b"
}) {
_docID
title
}
b31:add_Book(input: {
title: "Infinite Jest",
genre: "Fiction",
plot: "A gargantuan, mind-altering tragi-comedy about the Pursuit of Happiness in America.",
rating: 4.25,
ratings: [3.1, 4.1, 4.5],
_authorID: "bae-b59928dc-fd05-5fb7-aea2-9b24af5ebcea"
}) {
_docID
title
}
b32:add_Book(input: {
title: "Consider the Lobster and Other Essays",
genre: "Nonfiction",
plot: "Do lobsters feel pain? Did Franz Kafka have a funny bone? What is John Updike's deal, anyway? And what happens when adult video starlets meet their fans in person? Essays that are also enthralling narrative adventures.",
rating: 4.18,
_authorID: "bae-b59928dc-fd05-5fb7-aea2-9b24af5ebcea"
}) {
_docID
title
}
b41:add_Book(input: {
title: "Les Misérables",
genre: "Fiction",
plot: "Victor Hugo's tale of injustice, heroism and love follows the fortunes of Jean Valjean, an escaped convict determined to put his criminal past behind him.",
rating: 4.21,
ratings: [3.9, 4.1],
_authorID: "bae-c169e917-df52-5603-9224-39c1757f1b04"
}) {
_docID
title
}
}

Single fields

Return books with title "1984"
{
Book(filter: {
title: { _eq: "1984" }
}) {
title
genre
plot
}
}
Result
{
"data": {
"Book": [
{
"genre": "Fiction",
"plot": "A masterpiece of rebellion and imprisonment where war is peace, freedom is slavery, and Big Brother is watching.",
"title": "1984"
}
]
}
}
It is all about love, is it not? – Return books containing "love" in their plot (flexible matching)
{
Book(filter: {
plot: { _ilike: "%love%" }
}) {
title
genre
plot
}
}
Result
{
"data": {
"Book": [
{
"genre": "Fiction",
"plot": "Victor Hugo's tale of injustice, heroism and love follows the fortunes of Jean Valjean, an escaped convict determined to put his criminal past behind him.",
"title": "Les Misérables"
}
]
}
}

To filter on a single field, use the syntax fieldName: { operator: Value }, where:

  • fieldName – Name of the collection field to compare against.
  • operatorComparison operator to use.
  • Value – Value to compare against, of the same type of fieldName.

You need to explicitly specify the _and operator in case of two filters on the same field, because JSON objects cannot contain duplicate fields:

Valid – Multiple filters on same field with explicit operator
filter: {
_and: [
{ rating: { _gte: 4 } },
{ rating: { _lte: 5 } }
]
}
Invalid – Multiple filters on same field without operator
filter: {
rating: { _gte: 4 },
rating: { _lte: 5 }
}

Multiple fields

Additional fields listed in the filter object are implicitly combined with an AND operator.

Return books with title "1984" and genre "Fiction"
{
Book(filter: { # filters combined with AND by default
title: { _eq: "1984" },
genre: { _eq: "Fiction" }
}) {
title
genre
plot
}
}
Result
{
"data": {
"Book": [
{
"genre": "Fiction",
"plot": "A masterpiece of rebellion and imprisonment where war is peace, freedom is slavery, and Big Brother is watching.",
"title": "1984"
}
]
}
}

To use other operators and nested comparisons, use the syntax

filter: {
operator: [ { fieldName: Value }, ... ],
...
}
  • operatorComparison operator to use.
  • fieldName – Name of the collection field to compare against.
  • Value – Value to compare against, of the same type of fieldName.
Retrieve all books that either have genre == "Fiction", or rating between 4 and 5
{
Book(
filter: {
_or: [
{ genre: { _eq: "Fiction" } },
{ _and: [
{ rating: { _geq: 4 } },
{ rating: { _leq: 5 } },
] },
]
}
) {
title
genre
rating
}
}
Result
{
"data": {
"Book": [
{
"genre": "Fiction",
"rating": 3.7,
"title": "Lord of the Flies"
},
{
"genre": "Nonfiction",
"rating": 4.18,
"title": "Consider the Lobster and Other Essays"
},
{
"genre": "Fiction",
"rating": 4.25,
"title": "Infinite Jest"
},
{
"genre": "Biography",
"rating": 4.09,
"title": "Down and Out in Paris and London"
},
{
"genre": "Fiction",
"rating": 4.21,
"title": "Les Misérables"
},
{
"genre": "Fiction",
"rating": 4.2,
"title": "1984"
}
]
}
}
note

The conditional keywords _and and _or accept an array, whereas _not accepts an object.

Filter all objects that *do not* have the genre "Fiction"
{
Book(
filter: { _not: { genre: { _eq: "Fiction" } } }
) {
title
genre
}
}
Result
{
"data": {
"Book": [
{
"genre": "Nonfiction",
"title": "Consider the Lobster and Other Essays"
},
{
"genre": "Biography",
"title": "Down and Out in Paris and London"
}
]
}
}

Relationship fields

Filters can access fields within nested objects, such as in relationships:

Filter books by genre and author's name
{
Book(filter: {
genre: { _eq: "Fiction" },
author: { name: { _eq: "George Orwell" } }
}) {
title
plot
}
}
Result
{
"data": {
"Book": [
{
"plot": "A masterpiece of rebellion and imprisonment where war is peace, freedom is slavery, and Big Brother is watching.",
"title": "1984"
}
]
}
}

The syntax to filter over sub-objects has one more level of nesting in field names: relFieldName: { fieldName: { operator: Value } }, where:

  • relFieldName, fieldName – Name of the collection field to compare against.
  • operatorComparison operator to use.
  • Value – Value to compare against, of the same type of fieldName.

One-to-many relationships

When filtering over one-to-many relationships from the many side, a document is returned if at least one of the linked documents fulfills the conditions: not all documents need to match the conditions.

For example, when filtering over people that have authored books of genre Fiction, every person that has at least one fiction book among their authored books will be returned:

{
Person(filter: {
authoredBooks: { genre: { _eq: "Fiction" } }
}) {
name
}
}
Result
{
"data": {
"Person": [
{
"name": "George Orwell"
},
{
"name": "William Golding"
},
{
"name": "David Foster Wallace"
},
{
"name": "Victor Hugo"
}
]
}
}

If the return fields include the sub-object you filter on, the same filter is not applied to the result unless otherwise specified. For example, when filtering over people who have authored Fiction books, the returned books will include books of any genre:

Get persons who have authored at least one fiction book; return their names and *all* their authored books
{
Person(filter: {
authoredBooks: { genre: { _eq: "Fiction" } }
}) {
name
authoredBooks {
title
genre
}
}
}
Result
{
"data": {
"Person": [
{
"authoredBooks": [
{
"genre": "Biography",
"title": "Down and Out in Paris and London"
},
{
"genre": "Fiction",
"title": "1984"
}
],
"name": "George Orwell"
},
{
"authoredBooks": [
{
"genre": "Fiction",
"title": "Lord of the Flies"
}
],
"name": "William Golding"
},
{
"authoredBooks": [
{
"genre": "Nonfiction",
"title": "Consider the Lobster and Other Essays"
},
{
"genre": "Fiction",
"title": "Infinite Jest"
}
],
"name": "David Foster Wallace"
},
{
"authoredBooks": [
{
"genre": "Fiction",
"title": "Les Misérables"
}
],
"name": "Victor Hugo"
}
]
}
}

You can override this behavior by specifying a different filter on the sub-object in the result fields. When specified explicitly, root-level and sub-objects filters are evaluated indipendently: the root filter is applied first and the sub-object filter is applied on the given field, per each returned document.

Return all fiction books from George Orwell
{
Person(filter: { name: { _eq: "George Orwell" } }) {
name
authoredBooks(filter: { genre: { _eq: "Fiction" } } ) {
title
genre
}
}
}
Result
{
"data": {
"Person": [
{
"authoredBooks": [
{
"genre": "Fiction",
"title": "1984"
}
],
"name": "George Orwell"
}
]
}
}

JSON fields

If a JSON field is indexed, queries can traverse the JSON structure and filter by its inner properties. For example, with the following setup, it is possible to filter on i.love:

Schema for "jsonBlob" collection
type jsonBlob {
jsonField: JSON @index
}
A document with a JSON property
mutation {
add_jsonBlob(input: {
jsonField: {
i: {
love: "eating my family and commas"
}
}
}) { jsonField }
}
Filter for JSON's inner properties
{
jsonBlob(filter: {
jsonField: {
i: {
love: { _like: "%family%" }
}
}
}) { jsonField }
}
Result
{
"data": {
"jsonBlob": [
{
"jsonField": {
"i": {
"love": "eating my family and commas"
}
}
}
]
}
}
important

It is possible to filter for a JSON field's inner properties, but it's not possible to return them.

Invalid – Return JSON field inner properties
{
jsonBlob {
jsonField {
i {
love
}
}
{
}

Renamed fields (aliases)

You can filter over renamed fields via the _alias key. Alias names cannot be used directly in the filter object.

Valid – Filter a renamed field with _alias
{
Book(filter: { _alias: { bookTitle: { _eq: "1984" }}}) {
bookTitle: title
}
}
Invalid – Filter a renamed field directly
{
Book(filter: { bookTitle: { _eq: "1984" }}) {
bookTitle: title
}
}

List fields

The list operators _any, _none, _all evaluate a scalar operator on the elements of a list or JSON field and return a boolean. For example, _any: { _lt: 3.5 } evaluates to true if all the elements of the list are lower than 3.5. List operators yield false on empty lists, null values, or non-list fields.

Return books having only ratings of at least 3.9
{
Book(filter: {
ratings: { _all: { _geq: 3.9 } }
}) {
_docID
title
}
}
Result
{
"data": {
"Book": [
{
"_docID": "bae-d056ef07-f21d-5c0b-885b-25c35f04dea8",
"title": "Les Misérables"
}
]
}
}
Return books having at least one rating lower than 3.5
{
Book(filter: {
ratings: { _any: { _lt: 3.5 } }
}) {
_docID
title
}
}
Result
{
"data": {
"Book": [
{
"_docID": "bae-40292ec1-ab26-5184-8d63-486392e53dc4",
"title": "Infinite Jest"
},
{
"_docID": "bae-fca338d5-6a73-5676-8ae7-701165bd4f03",
"title": "1984"
}
]
}
}
Return books having not even one rating lower than 3.0
{
Book(filter: {
ratings: { _none: { _lt: 3.0 } }
}) {
_docID
title
}
}
Result
{
"data": {
"Book": [
{
"_docID": "bae-40292ec1-ab26-5184-8d63-486392e53dc4",
"title": "Infinite Jest"
},
{
"_docID": "bae-d056ef07-f21d-5c0b-885b-25c35f04dea8",
"title": "Les Misérables"
}
]
}
}

Operators and types

Scalar operators

OperatorDescription
_eqEqual to
_neqNot Equal to
_gtGreater Than
_geqGreater or Equal to
_ltLess Than
_leqLess or Equal to
_inIn list
_ninNot In list
_likeLike sub-string (supports % wildcard)
_ilikeCase-Insensitive Like sub-string (supports % wildcard)
_nlikeNot like sub-string (supports % wildcard)
_nilikeNot like case-Insensitive sub-string (supports % wildcard)

List operators

OperatorDescription
_anytrue if at least one element is true
_nonetrue if none of the elements are true
_alltrue if all of the elements are true

Operators supported by type

Scalar TypeOperators
String, Blob_eq, _neq, _like, _ilike, _nlike, _nilike, _in, _nin
Int, Float_eq, _neq, _gt, _geq, _lt, _leq, _in, _nin
Boolean, ID_eq, _neq, _in, _nin
DateTime_eq, _neq, _gt, _geq, _lt, _leq, _in, _nin
JSON_any, _all, _none, _eq, _neq, _like, _ilike, _nlike, _nilike, _in, _nin
List_any, _all, _none, _eq, _neq