---
title: Query Syntax (Legacy)
slug: dql/UAopX0p28gyjw3guV1APQ
docTags: 
createdAt: 2023-09-29T16:29:14.659Z
---

At a high-level, queries operate on collections rather than individual documents. Filter, search, and retrieve specific information based on various criteria using Boolean operators, equal and unequal operators, comparison operators, and match operators. 

This article includes an overview of operators and path navigations for building advanced queries in your app, along with real-world examples.

For related information, see the *Platform Manual:*

- [Data Types](docId\:p7TLPgP3eGtQyRVKb45QS)
- [Establishing Relationships](docId\:LBRSIPPkeZdqTGBM4i5NN)

# Boolean Operators

When a field property is a boolean data type, use explicit true-false values.&#x20;

:::hint{type="info"}
Enclose groups of logical operations with parentheses to ensure Ditto interprets your desired logic correctly.
:::

For example, to find documents with an `"isDeleted"` boolean property set to `"true"`:

:::CodeblockTabs
Query

```sql
"isDeleted == true"
```
:::

To find documents with an `"isDeleted"` boolean property set to `"false"`:

:::CodeblockTabs
Query

```sql
"isDeleted == false"
```
:::

# Equal (==) and Inequality (!=) Operators

To find documents that match a given key-value pair, use the equal operator. Where you specify the key and the number or string value you want to match separated by `==`.&#x20;

For example, to find documents that have a title equal to `"Harry Potter"`:

:::CodeblockTabs
Query

```sql
"title == 'Harry Potter'"
```
:::

If, instead of finding documents that match, you want to find documents that do *not&#x20;*&#x6D;atch a given key-value pair, use the inequality operator. Where you specify the key and the value that you don’t want to match separated by `!=`.&#x20;

For example, to find documents that are not of the title "Lord of the Rings":

:::CodeblockTabs
Query

```sql
"title != 'Lord of the Rings'"
```
:::

# Comparison Operators: (>=)(>)(\<=)(\<)

Compare values in documents, set conditions, retrieve specific documents that meet your criteria, and make logical evaluations using the following operators in your query statements.

:::hint{type="info"}
Ditto supports parsing ISO-8601 date strings, so you can use ISO-8601 formatted date strings in queries for comparison operations. For more information, see [Using ISO-8601 for Date Strings](docId\:LBRSIPPkeZdqTGBM4i5NN).
:::

For example:

To find documents where `age` field property is less than or equal to the value of `18`:

:::CodeblockTabs
Query

```sql
"age <= 18"
```
:::

To find documents where the `age` field property is less than the value of `18`:

:::CodeblockTabs
Query

```sql
"age < 18"
```
:::

To find documents where the `age` field property is greater than or equal to the value of `18`:

:::CodeblockTabs
Query

```sql
"age >= 18"
```
:::

To find documents where the `age` field property is greater than the value of `18`:

:::CodeblockTabs
Query

```sql
"age > 18"
```
:::

# Compound Operators

Perform complex operations in a single executable by using *compound operators*. A compound operator is a combination of two or more operators in a single executable:&#x20;

| **SQL**       | **Ditto**   |
| ------------- | ----------- |
| `AND`         | `&&`        |
| `OR`          | `\|\|`      |
| `NOT`         | `!`         |
| `contains( )` | contains( ) |

## Logical AND Predicate Statements: (&&)

Similar to SQL `AND` statements, use `&&` for a condition that evaluates to true only when *all&#x20;*&#x6F;f its conditions are set to `true`.

For example, to find documents that have a `theme` field property equal to `"Dark"` and a name field property equal to `"Light"`:

:::CodeblockTabs
Query

```sql
"theme == 'Dark' && name == 'Light'
```
:::

## Logical OR Statements: (||)

Similar to SQL `OR` statements, use `||` for a logical *or* predicate statement.

For example, to find documents that are `"Tom"` or `"Arthur"`:

:::CodeblockTabs
Query

```sql
"name == 'Tom' || name == 'Arthur'"
```
:::

## Logical NOT Statements: (!)

Similar to SQL `NOT` statements, use `!` for logical *not* predicate statements:

For example, find documents that are neither "Hamilton" nor "Morten":

:::CodeblockTabs
Query

```sql
"name != 'Tom'"
```
:::

## String Operations

Use `starts_with(property, test)` to test if a field property with a string value starts with a test string.

For example, to find documents with a `title` field property that *begins* with `"Lord"`:

:::CodeblockTabs
Query

```sql
"starts_with(title, 'Lord')"
```
:::

Use `ends_with(property, test)` to test if a field property with a string value *ends* with a test string.&#x20;

For example, to find documents with a `title` field property that ends with `"Rings"`:

:::CodeblockTabs
Query

```sql
"ends_with(title, 'Rings')"
```
:::

Use `regex(property, test)` to see if a field property with a string value passes a regular expression. For more information, see the official Mozilla Developer Network Docs (MDN) > [Regular Expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions).

For example, to find documents containing only upper and lowercase letters, numbers, and underscores:

:::CodeblockTabs
Query

```sql
"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
```
:::

# NULL Values

Use `null` to check for the existence of a value of a given field.

For example, to find documents with a `color` field property that has no value:

:::CodeblockTabs
Query

```sql
"color == null"
```
:::

# Array Operators

When handling collections of data that different peers may make concurrent updates to, first consider using an embedded `map` structure. If necessary, use an `array`.&#x20;

The `array` type in Ditto is a CRDT and behaves differently than the primitive `array` type. For more information, see the *Platform Manual&#x20;*> [Data Types](docId\:p7TLPgP3eGtQyRVKb45QS).

:::hint{type="warning"}
Avoid using `arrays` in Ditto.&#x20;

Due to potential merge conflicts when offline peers reconnect to the mesh and attempt to sync their updates, especially when multiple peers make concurrent updates to the same item within the `array`.
:::

| **Operator**             | **Operation**                   |
| ------------------------ | ------------------------------- |
| `contains(array, value)` | Checks for value in the `array` |

:::CodeblockTabs
Query

```sql
"contains(['blue', 'green'], color]"
```
:::

# Date and Time Formats

When parsing date and time strings, use the ISO-8601 standard format, as follows.&#x20;

For more information, see *Platform Manual&#x20;*> [Using ISO-8601 for Date Strings](docId\:Xa_69cUyuDNotwcJSfCbv).

:::CodeblockTabs
Query

```sql
"created_at >= '2022-04-29T00:55:31.859Z'"
```
:::

# Field Path Navigation

If fields consist of alphanumeric characters or include underscores, use the following bracket notation to navigate document properties:

:::CodeblockTabs
Query

```sql
"work['street-line'] == '678 Johnson Street'"
```
:::

## Valid Path Definitions

:::BlockQuote
`a[0][1]["_123"]`
`a["0"]["1"]`
`[”a”][”0”][”1”]`
:::

## Invalid Path Definitions

:::BlockQuote
`$foo` ($ isn't a valid character anywhere in the unquoted string)

`a[1st]` (1st isn't a valid unquoted string for field access, as the first character is a number)

`b[2nd]` (same reason as above)

`b[$foo]` ($ isn't a valid character anywhere in the unquoted string)

`b[foo$]` (same reason as above)

`a["foo"]b` (missing \[""] around b)
:::

***Instead use...***

:::BlockQuote
`["$foo"]`

`a["1st"]`

`b["2nd"]`

`b["$foo"]`

`b["foo$"]`

`b["foo"]["b"]`
:::

