Querying Ditto Documents

Syntax

Ditto provides a robust query engine that supports different filter operations. At a high-level, all queries work on a specific collection and are used to filter the collection. In addition, since Ditto works with data represented in JSON-compatible documents, the query syntax offers dot notation to reference keys within the document tree as shown below:

let collection = ditto.store.collection("people")
    .find("favoriteBooks[0].title == 'The Great Gatsby'")
    .exec()
NSArray *docs = [[[ditto.store collection:@"people"]
                    find:@"favoriteBooks[0].title == 'The Great Gatsby'"] exec];
val results = ditto.store.collection("people")
    .find("favoriteBooks[0].title == 'The Great Gatsby'")
    .exec()
List<DittoDocument> results = ditto.store.collection("people")
    .find("favoriteBooks[0].title == 'The Great Gatsby'")
    .exec();
var results = ditto.Store.Collection("people")
    .Find("favoriteBooks[0].title == 'The Great Gatsby'")
    .Exec();
std::vector<Document> results = ditto.store.collection("people")
    .find("favoriteBooks[0].title == 'The Great Gatsby'")
    .exec();
const collection = await ditto.store.collection('people')
    .find("favoriteBooks[0].title == 'The Great Gatsby'")
    .exec()

Dot Notation

To refer to keys within the document tree, specifically the key's path, Ditto uses dot notation. For example with the following document contents:

{
   "name": { "first": "Alan", "last": "Turing" },
   "contact": { "phone": { "type": "cell", "number": "111-222-3333" } }
}

you would reference the last name like this:

   find("name.last == 'Turing'")

Keys in the query syntax by default must be alphanumeric or include underscore (a-zA-Z0-9_). In addition, the key must start with an alpha characters first (a-zA-Z_). If your key uses another character, such as a hyphen, like full-names you must bracket it: ["full-names"] or outerKey["full-names"] when referencing it within a query.


Comparisons

Equality

==

Left hand expression is equal to right hand expression

   find("books[0].title == 'Harry Potter'")

Greater Or Less Than

>= or >

Left hand expression is greater than or equal to right hand expression

   find("age >= 18")

=< or <

Left hand expression is less than or equal to right hand expression

   find("age <= 18")

Not Equal

!=

Left hand expression is not equal to right hand expression

   find("age != 18")

Compound Predicates

And

&&

This is a Logical and Predicate; similar to SQLite's AND

   find("theme == 'Dark' && name == 'Light'")

Or

||

This is a Logical or Predicate; similar to SQLite's Or

   find("name == 'Tom' || name == 'Arthur'")

Not

!

This is a Logical Not Predicate; similar to SQLite's NOT

   find("!(name == 'Hamilton' || name == 'Morten')")

Contains

contains(array, value)

Right hand parameter must appear in the array specified by left hand parameter.

   find("contains(['bluetooth', 'wifidirect'], connectionType)")

Array Operations

Index Accessor

array[index]

Specifies the element at the specified index in the array

   find("books[0].title == 'Harry Potter'")

Length

length(jsonPath)

Specifies the size of the array

   find("length(doc.tags) >= 2")

Sum

sum(jsonPath)

Returns the sum of the array of numbers

   find("sum(doc.prices) > 100")

String Operations

Begins With

beginsWith(jsonPath, stringValue)

Left hand parameter begins with the right hand parameter

   find("beginsWith(doc.title, 'Lord of the')")

Ends With

endsWith(jsonPath, stringValue)

Left hand parameter ends with the right hand parameter

   find("endsWith(doc.title, 'Rings')")

Regex

regex(jsonPath, regexStringValue)

Left hand expression or parameter equals the right hand expression using a regex comparison

   find("regex(doc.title, '^s')")

Sort

Ditto supports sorting a query based on a specific key:

let sortedRedCars = ditto.store.collection("cars")
    .find("color == 'red'")
    .sort("miles", direction: .ascending)
    .exec()
NSArray *sortedRedCars = [[[[ditto.store collection:@"cars"]
                  find:@"color == 'red'"]
                  sort:@"miles" direction:DITSortDirectionAscending] exec];
val sortedRedCars = ditto.store.collection("cars")
    .find("color == 'red'")
    .sort("miles", DittoSortDirection.Ascending)
    .exec()
List<DittoDocument> sortedRedCars = ditto.store.collection("cars")
    .find("color == 'red'")
    .sort("miles", DittoSortDirection.Ascending)
    .exec();
var sortedCars = ditto.Store.Collection("cars")
    .Find("color == 'red'")
    .Sort("miles", direction: DittoSortDirection.Ascending)
    .Exec();
std::vector<Document> sorted_and_limited_red_cars = ditto.store.collection("cars")
    .find("color == 'red'")
    .sort("miles", SortDirection::ascending)
    .limit(100)
    .exec();
const sortedRedCars = await ditto.store.collection('cars')
    .find("color == 'red'")
    .sort('miles', 'ascending')
    .exec()

Limit

Ditto supports limiting a query to a specific number of documents:

let sortedAndLimitedRedCars = ditto.store.collection("cars")
    .find("color == 'red'")
    .sort("miles", direction: .ascending)
    .limit(100)
    .exec()
NSArray *sortedAndLimitedRedCars = [[[[[ditto.store collection:@"cars"]
                  find:@"color == 'red'"]
                  sort:@"miles" direction:DITSortDirectionAscending]
                  limit:100] exec];
val sortedAndLimitedRedCars = ditto.store.collection("cars")
    .find("color == 'red'")
    .sort("miles", DittoSortDirection.Ascending)
    .limit(100)
    .exec()
List<DittoDocument> sortedAndLimitedRedCars = ditto.store.collection("cars")
    .find("color == 'red'")
    .sort("miles", DittoSortDirection.Ascending)
    .limit(100)
    .exec();
var sortedAndLimitedRedCars = ditto.Store.Collection("cars")
    .Find("color == 'red'")
    .Sort("miles", direction: DittoSortDirection.Ascending)
    .Limit(100).Exec();
std::vector<Document> sorted_and_limited_red_cars = ditto.store.collection("cars")
    .find("color == 'red'")
    .sort("miles", SortDirection::ascending)
    .limit(100)
    .exec();
const sortedAndLimitedRedCars = await ditto.store.collection('cars')
    .find("color == 'red'")
    .sort('miles', 'ascending')
    .limit(100)
    .exec()
Top