Querying
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["people"] .find("favoriteBook.title == 'The Great Gatsby'") .exec()
Using query variables with $args
Often, you will query with runtime variables. Instead of building or
interpolating query strings, the query system will accept variables through an
$args
dictionary object.
let documents = ditto.store["users"].find("name == $args.name && age <= $args.age", args: [ "age": 32, "name": "Max"]).exec()
Find by _id
Every document contains its own unique _id
property. This property can be set or randomly assigned. When updating a single document within a collection you will most often find that document by its _id
property.
// finds the document with the specified _idfindByID("1234")
Sort
Before executing a query, you can specify to sort on a specific property. Call sort
before a query is executed by specifying a specific property and a sort direction.
Note: Queries that do not specify a sort
will return documents in an arbitrary order.
The following example will sort on documents that have a mileage property
let sortedRedCars = ditto.store.collection("cars") .find("color == 'red'") .sort("miles", direction: .ascending) .exec()
Limit
There are times where you need to limit the number of results that a query returns. Call limit
before the query is executed to trim the number of results. This is best used with sort
.
let sortedAndLimitedRedCars = ditto.store.collection("cars") .find("color == 'red'") .sort("miles", direction: .ascending) .limit(100) .exec()
Creating query strings
The Ditto query language is very similar to what you'd write in most if
statements. In addition, we offer standard, easy-to-understand query condition
operators that most developers should understand.
info
On the small peer, there are no secondary indexes. Queries such as status ==
'Active'
will have to perform a full table scan.
Navigating Document Properties
To refer to keys within the document's property tree, Ditto uses dot notation that should be familiar to most developers. Let's say we have a document like so:
{ "_id": "123abc", "name": { "first": "Alan", "last": "Turing" }, "contact": { "phone": { "type": "cell", "number": "111-222-3333" } }, "work": { "street-line": "678 Johnson Street"}}
If you wanted to query for the last
property nested in name
, you will need to do the following:
"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, you must use a brack syntax. To query for the "street-line"
property underneath "work"
, you will need to do the following:
"work['street-line'] == '678 Johnson Street'"
Equality ==
, Inequality
// finds documents which have a title equal to Harry Potter."title == 'Harry Potter'"
// finds documents which that are not of the title Lord of the Rings"title != 'Lord of the Rings'"
Comparisons - Greater Or Less Than >=
, >
, <
, <=
// finds documents where the age is less than or equal to 18"age <= 18"// finds documents where the age is less than to 18"age < 18"// finds documents where the age is greater than or equal to 18"age >= 18"// finds documents where the age is greater than to 18"age > 18"
Compound - And &&
, Or ||
, Not !
, Contains contains
Use &&
for a logical and Predicate; similar to SQL AND statements.
// finds documents that have a theme property equal to "Dark" and a name property equally to "Light""theme == 'Dark' && name == 'Light'
Use ||
for a logical or predicate; similar to SQL OR statements
// finds documents that are "Tom" or "Arthur""name == 'Tom' || name == 'Arthur'"
Use !
for a logical not predicate; similar to SQL NOT statements
// finds documents that are neither "Hamilton" nor "Morten""!(name == 'Hamilton' || name == 'Morten')"
Make sure you wrap all chained boolean operators in parenthesis:
// chained boolean operators need parens"(theme == 'Dark' && name == 'Light') || finished == false"
Use contains(array, value)
to check if an array contains a value.
// finds documents who have a `connectionType` property and checks if it equals any of the values in a defined array"contains(['bluetooth', 'wifidirect'], connectionType)"
String Operations
Use starts_with(property, test)
to test if a property with a string value starts with a test string
// finds documents with a title property that begins with "Lord""starts_with(title, 'Lord')"
Use ends_with(property, test)
to test if a property with a string value ends with a test string
// finds documents with a title property that ends with "Rings""ends_with(title, 'Rings')"
Use regex(property, test)
to see if a property with a string value passes a Regular Expression. Click here for a reference.
// finds documents which has a title property that only comprises of upper and lowercase letters, numbers, and underscores. "regex(title, '^([A-Za-z]|[0-9]|_)+$')"
// A title property of "abc129_24A" will pass// A title property of "abc129_24A 3" will not pass
Dates
Queries also parse ISO-8601 date strings as comparable dates:
"created_at >= '2022-04-29T00:55:31.859Z'"
Booleans
Use when your property is of type Boolean, use value == false
or value == true
explicitly.
//finds documents which have an 'isDeleted' boolean propety set to `true`"isDeleted == true"
//finds documents which have an 'isDeleted' boolean propety set to `false`"isDeleted == false"