Finding and Observing
This article provides an overview of essential methods for document retrieval, query formulation, and realtime monitoring.
Just like with conventional database querying, you execute query operations to fetch one or more documents that satisfy specific criteria and conditions, as well as to set up listeners, referred to as subscriptions, for the data you're interested in watching.
Use the find and findById methods for executing single queries against the local Ditto store. Once invoked, these methods retrieve documents based on the query you provided as an argument:
Additionally, when working with dynamic changes, for ease, convenience, and flexibility, you can define and use values within a top-level args variable for your queries, as opposed to needing to separately adjust each individual query structure and conditions change.
For more information, see $args for Dynamic Data.
The Find method executes a single query against the Ditto store, targeting to retrieve one or more documents within a given collection based on certain criteria.
You can search for documents within a collection against a wide range of criteria, from very broad conditions to more specific filters.
For instance, you can look for documents in a collection based on general conditions, such as "find all documents in the 'cars' collection with the field 'color' set to 'blue'."
Or narrow the focus of your search and use various filter options, including comparison operators (like greater than, less than), logical operators (AND, OR), upon many other tools Ditto offers for precisely adjusting your filters. For an overview of the filter options you can use to create complex search criteria in your queries, see Ditto Basics > Query Syntax.
In your find function, indicate the document collection to query and define a condition that determines which documents to return.
For example, the following find function, when invoked, searches the cars collection for documents with the field color set to blue:
The Ditto query engine supports various filter operations for optimal data retrieval.
As the basis of data organization and access in Ditto, the query engine indexes the document _id so you can quickly and precisely access your data.
The first set of fields within each document uniquely identifies the data that its document object encodes. When grouped in a collection, this _id serves as the primary key identifying the document in the collection.
Each document must be assigned a unique identifier. When invoking the upsert method to create a new document, unless manually supplied, Ditto automatically generates and assigns the new document a 128‑bit Universally Unique Identifier (UUID).
For instructions on how to fetch a document by _id, see any of the following as appropriate:
- Default UUID: If you did not supply a custom document ID, see String ID Lookup for instructions on retrieving a document by its Ditto-generated and -assigned UUID.
- Custom string: If you provided a string value for the _id parameter when calling the Upsert API during document creation, see String ID Lookup.
- Custom JSON blob object: If you provided two or more embedded fields for the _id parameter when calling the Upsert API during document creation, see Composite ID Lookup.
Fetch a single document by its primary key: the document _idfield by invoking the Find By ID method.
The following snippet demonstrates a Find By ID operation that, once called, searches for the document assigned the 123456 unique identifier:
Handling dynamic-changing data introduces challenges that impact your end-user experience, as well as the maintainability, security, and performance of your app.
For example, the following snippet illustrates a local query using the string "color == $args.color":
In addition to using various operators and string formats to construct conditions in your queries, you can also control the results that are returned from calls to the Find and Find By ID functions:
Restrict the number of results returned by your query by using the Limit method to specify the number of results you want to return.
The following snippet demonstrates a Limit operation set for 100 query results:
Sort the results by a specific order using the Sort method. With the Sort method, you specify the field to match and the desired order for arranging the matching query results, as follows:
By default, queries that do not include a sort operation filter by document ID.
The following snippet demonstrates a sort operation on the miles field with results arranged in ascending order:
To enhance query efficiency, you can perform both sort and limit operations within a single query, as follows:
In scenarios where you want to continuously watch changes occurring to your local Ditto store in realtime, use live queries. With a live query, you signal which changes you're interested in watching and define the callback function that you want Ditto to trigger in response.
Additionally, you can incorporate both time-based and state-based replication techniques into your app's design patterns. For more information, see Use Cases > State-Based Replication and Time-Based Replication.
For organization and management, you can create a Live Query object to store a single live query or multiple live queries, as well as a custom class that encapsulates the logic for managing your live queries.
To set up a single live query, as demonstrated in the following snippet:
- In the top-most scope of your app, declare a Live Query object.
- Specify the event you're interested in watching; for example, the cars collection where the color is black.
- Using the Observe Local method, define the subsequent liveQuery callback function that you want Ditto to execute in your app. For more information, see Constructing Live Query Callback Functions, as follows.
For example, the following snippet demonstrates an observeLocal method that monitors changes in the cars collection where the color is "blue".
Once the changes occur, the total number of documents displays to the end user.
If you're not using a Reactive framework, consider reacting to changes from a Live Query Event object. A Live Query Event object is a dynamic query that, as changes occur, automatically updates Ditto in realtime.
Reactive frameworks — like React, Jetpack Compose, and SwiftUI — provide tooling and various features to make UI development more efficient and help you build responsive apps with minimal effort.
These Reactive frameworks do this by abstracting away the low-level details of updating UI, managing state, and rendering components; eliminating the need to manually implement a diffing algorithm. For more information, see React's official documentation > Learn React.
A LiveQuery callback consists of two arguments: docs and event. The docs argument specifies your collection and the event argument identifies which documents have changed.
The following table provides an overview of events in Ditto:
The first event that will be delivered (and delivered only once).
The event to return each time the results of your live query change. It contains information about the set of documents that previously matched the query before the update, along with information about what documents have been inserted, removed, updated, or moved (upserted), as part of the set of matching documents.
To create multiple live queries stored in a single LiveQuery object that you can use to add live queries, remove specific ones, and stop all live queries at once, using either an array or a map, create a custom class that encapsulates your management logic.
For more information about Ditto arrays and maps, see Data Types.
To cancel a live query, call cancel or stop on the live query object you initially set up to establish the live query.
Once canceled, the live query stops receiving updates.