---
title: Finding and Observing
slug: v4-4/jRA2j_xb7X1u_Zagzx-8n
docTags: 
createdAt: 2023-07-28T20:04:28.318Z
---

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.

- [Find Method](./#find-method)
- [Observe Local Method](./#observe-local-method)

# Find Method

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:

- To search for multiple documents based on various filters, use the `find` method. ([findById: Fetch by Collection](./#finding-by-document-id))

- To target a single document by its`_id`, use the `findById` method. ([FindById: Fetch by Document ID](./#finding-by-document-id))

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.&#x20;

For more information, see [$args for Dynamic Data](./#using--args-for-dynamic-data).

## Finding by Query

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.&#x20;

You can search for documents within a collection against a wide range of criteria, from very broad conditions to more specific filters.&#x20;

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&#x20;*> [Query Syntax](docId\:MMTiSmYkR3HxZmYS1bi2w).

In your `find` function, indicate the document collection to query and define a condition that determines which documents to return.&#x20;

:::CodeblockTabs
```swift
val documents = ditto.store
    .collection("your_collection_name")
    .find([query], [arguments])
    .exec()
```

```kotlin
val documents = ditto.store
    .collection("your_collection_name")
    .find([query], [arguments])
    .exec()
```

```javascript
const documents = await ditto.store
    .collection("your_collection_name")
    .find([query], [arguments])
    .exec()
```

```java
List<DittoDocument> documents = ditto.store
  .collection("your_collection_name")
  .find([query], [arguments])
  .exec();
```

```csharp
var documents = ditto.Store
  .Collection("your_collection_name")
  .Find([query], [arguments])
  .Exec();
```

```cpp
std::vector<Document> documents = ditto.get_store()
  .collection("your_collection_name")
  .find([query], [arguments])
  .exec()
```

```rust
let collection = ditto.store()
  .collection("your_collection_name").unwrap();

collection
  .find([query])
  .exec()?;
```
:::

For example, the following `find` function, when invoked, searches the `cars` collection for documents with the field `color` set to `blue`:

:::CodeblockTabs
```swift
let documents = ditto.store
    .collection("your_collection_name")
    .find("color == blue")
    .exec()
```

```kotlin
val documents = ditto.store
    .collection('cars')
    .find("color == blue")
    .exec()
```

```javascript
const documents = await ditto.store
      .collection('cars')
      .find("color == blue")
      .exec()
```

```java
List<DittoDocument> documents = ditto.store
  .collection('cars')
  .find("color == blue")
  .exec();
```

C#

```csharp
var documents = ditto.Store
  .Collection("cars")
  .Find("color == blue")
  .Exec();
```

```cpp
std::vector<Document> documents = ditto.get_store()
  .collection("cars")
  .find("color == 'blue'")
```

```rust
let documents = collection
  .find("color == \'blue\'")
  .exec()?;
```
:::

## Finding By Document ID

The Ditto query engine supports various filter operations for optimal data retrieval.&#x20;

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.&#x20;

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).&#x20;

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](./#retrieving-by-string-id) for instructions on retrieving a document by its Ditto-generated and -assigned UUID.&#x20;

- Custom `string`: If you provided a `string` value for the `_id `parameter when calling the Upsert API during document creation, see [String ID Lookup](./#retrieving-by-string-id).

- 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](./#retrieving-by-composite-id).

### Retrieving by String ID

Fetch a single document by its primary key: the document `_id`field by invoking the Find By ID method.

:::CodeblockTabs
```swift
let documents = ditto.store
    .collection("your_collection_name")
    .findByID([id],)
    .exec()
```

```kotlin
val documents = ditto.store
    .collection("your_collection_name")
    .findById("id")
    .exec()
```

```javascript
const document = await ditto.store
.collection("cars")
.findById("123456")
.exec()
```

```java
List<DittoDocument> documents = ditto.store
  .collection("your_collection_name")
  .findById([id])
  .exec();
```

```csharp
var documents = ditto.Store
  .Collection("your_collection_name")
  .Find([query], [arguments])
  .Exec();
```

```cpp
Document document = ditto.get_store()
  .collection("your_collection_name")
  .find_by_id([id]);
```

```rust
let document = collection
  .find_by_id([id])
  .exec()?;
```
:::

The following snippet demonstrates a Find By ID operation that, once called, searches for the document assigned the `123456` unique identifier:

:::CodeblockTabs
```swift
let document = ditto.store
    .collection("cars")
    .findByID("123456")
    .exec()
```

```kotlin
val documents = ditto.store
    .collection("cars")
    .findById("123456")
    .exec()
```

```javascript
const document = ditto.store
.collection("your_collection_name")
.findById([compositeKey])
.exec()
```

```java
List<DittoDocument> documents = ditto.store
    .collection("cars")
    .findById("123456")
    .exec();
```

```csharp
var document = ditto.Store.Collection("cars").FindById("123456").Exec();
```

```cpp
Document document = ditto.get_store()
  .collection("cars")
  .find_by_id("123456");
```

```rust
let document = collection.find_by_id("123456").exec()?;
```
:::

### Retrieving by Composite ID&#x20;

If supplying your own document ID, you can encode your value in a `string` or, if forming a composite key, a JSON-object.&#x20;

:::hint{type="warning"}
You can configure a custom document ID only at the time of document creation.&#x20;

Once a document is created, to ensure consistency and uniqueness throughout the platform, the unique identifier that either Ditto automatically generated and assigned or you manually assigned becomes permanent and cannot be changed at a later time.
:::

:::CodeblockTabs
```swift
let document = ditto.store
    .collection("cars")
    .findByID([compositeKey])
    .exec()
```

```kotlin
val document = ditto.store
    .collection("cars")
    .findById(compositeKey)
    .exec()
```

```javascript
const query = "field == $args.field"
const args = { value: set_value }
const documents = await ditto.store.collection("your_collection_name").find(query, args).exec()
```

```java
List<DittoDocument> documents = ditto.store
  .collection("your_collection_name")
  .findById([composite key]) 
  .exec();
```

```csharp
var document = ditto.Store
.Collection("your_collection_name")
.FindById([id])
.Exec();
```

```cpp
const document = ditto.get_store()
.collection("your_collection_name")
.find_by_id(composite_key);
```

```rust
let document = ditto.get_store()
    .collection("your_collection_name")
    .find_by_id(composite_key);
```
:::

## Using $args for Dynamic Data

Handling dynamic-changing data introduces challenges that impact your end-user experience, as well as the maintainability, security, and performance of your app.

When invoking the Find and Observe Local methods to query values  that may change dynamically during runtime, you can declare a top-level `args` variable that defines the dynamic values, and then pass the the `$args` identifier within your query conditions.

That way, the query engine separates your query logic from the data so you can easily define and pass values as needed to adapt without having to change the query structure itself.

:::hint{type="warning"}
Using `strings` to filter dynamic data may impact the maintainability, security, and performance of your app by introducing various issues such as syntax errors in your code.
:::

:::CodeblockTabs
```swift
let args: [String: Any] = [
    "field1": "your_dynamic_field",
    "field2": "and_assigned_value"
]

let documents = ditto.store.collection("your_collection_name")
    .find("field1 == $args.field1 && field2 == $args.field2", args)
    .exec()
```

```kotlin
val args: Map<String, Any> = mapOf(
    "field1" to "your_dynamic_field",
    "field2" to "and_assigned_value"
)

val documents = ditto.store.collection("your_collection_name")
    .find("\$args.field1 == field1 && \$args.field2 == field2", args)
    .exec()
```

```javascript
const query = "field == $args.field"
const args = { value: set_value }
const documents = await ditto.store.collection("your_collection_name").find(query, args).exec()
```

```java
String query = "your_query"
HashMap<String, String> args = new HashMap<>();
argsMap.put("your_dynamic_field", "and_assigned_value");

List<DittoDocument> documents = ditto.store
  .collection("your_collection_name")
  .find(query, args)
  .exec();
```

```csharp
var query = "field == $args.field";
var args = new Map<string, object> { { "field", "value" }};
var documents = ditto.Store
  .Collection("your_collection_name")
  .Find(query, args)
  .Exec();
```

```cpp
```

```rust
let query = "field == $args.field";
let args = json!({ value: set_value });
let documents = ditto.store
  .collection("your_collection_name")
  .find(query, args)
  .exec()
```
:::

For example, the following snippet illustrates a local query using the string `"color == $args.color"`:

:::CodeblockTabs
```swift
let query = "color == $args.color"
let args = [ "color": "blue" ]
let documents = ditto.store
  .collection("your_collection_name")
  .find(query, args)
  .exec()
```

```kotlin
val foundDocs = ditto.store
    .collection("cars")
    .find("color == \$args.color", mapOf("color" to "blue"))
```

```javascript
const query = "color == $args.color";
const args = { color: "blue" };
const documents = await ditto.store
.collection("cars")
.find(query, args)
```

```java
String query = "color == $args.color";
HashMap<String, Object> args = new HashMap<>();
args.put("color", "blue");

List<DittoDocument> documents = ditto.store
  .collection("your_collection_name")
  .find(query, args)
  .exec();
```

```csharp
var query = "color == $args.color";
var args = new Map<string, object> { { "color", "blue" }};
var documents = ditto.Store
  .Collection("cars")
  .Find("color == blue", args)
  .Exec();
```

```cpp
const query = "color == $args.color"
const args = { color: blue }
std::vector<Document> documents = ditto.get_store()
  .collection('cars')
  .find(query, args)
```

```rust
let query = "color == $args.color"
let args = [ "color": "blue" ]
let documents = ditto.store
  .collection("cars")
  .find(query, args)
  .exec()
```
:::

## Limiting and Sorting Results

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:

- [Limiting Results](./#limit-method--restricting-results)
- [Sorting Results](./#s-ort-method-arranging-results)
- [Limiting and Sorting Results in a single operation](./#limit-and-sort-methods-in-a--single-executable)

### Limit Method: Restricting Results

Restrict the number of results returned by your query by using the Limit method to specify the number of results you want to return.

:::CodeblockTabs
```swift
let documents = ditto.store
    .collection("your_collection_name")
    .find([query], [arguments])
    .limit([value])
    .exec()
```

```kotlin
val sortedAndLimitedRedCars = ditto.store.collection("cars")
    .collection("your_collection_name")
    .find([query], [arguments])
    .limit([value])
    .exec()
```

```javascript
const documents = await ditto.store
  .collection("your_collection_name")
  .find([query], [arguments])
  .limit([value])
  .exec()
```

```java
List<DittoDocument> documents = ditto.store
  .collection("your_collection_name")
  .find([query], [arguments])
  .limit([value])
  .exec();
```

```csharp
var documents = ditto.store
  .Collection("your_collection_name")
  .Find([query], [arguments])
  .Limit([value])
  .Exec();
```

```cpp
std::vector<Document> documents = ditto.get_store()
  .collection("your_collection_name")
  .find([query], [arguments])
  .limit([value]);
```

```rust
let documents = collection
  .find([query], [arguments])
  .limit([value])
  .exec()?;
```
:::

The following snippet demonstrates a Limit operation set for `100` query results:

:::CodeblockTabs
```swift
let documents = ditto.store
  .collection("cars")
  .find("color == 'blue'")
  .limit(100)
  .exec()
```

```kotlin
val sortedAndLimitedRedCars = ditto.store.collection("cars")
    .find("color == 'red'")
    .sort("miles", DittoSortDirection.Ascending)
    .limit(100)
    .exec()
```

```javascript
const documents = await ditto.store
  .collection("cars")
  .find("color == 'blue'")
  .limit(100)
  .exec()
```

```java
List<DittoDocument> documents = ditto.store
  .collection("cars")
  .find("color == 'blue'")
  .limit(100)
  .exec();
```

```csharp
var documents = ditto.Store
  .Collection("cars")
  .Find("color == 'blue'")
  .Limit(100)
  .Exec();
```

```cpp
std::vector<Document> documents = ditto.get_store()
  .collection("cars")
  .find("color == 'blue'")
  .limit(100);
```

```rust
let documents =collection
  .find("color == \'blue\'")
  .limit(100)
  .exec()?;
```
:::

### Sort Method: Arranging 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:

:::hint{type="info"}
By default, queries that do not include a `sort` operation filter by document ID.&#x20;
:::

:::CodeblockTabs
```swift
let documents = ditto.store
    .collection("your_collection_name")
    .find([query], [arguments])
    .sort([field], [.ascending|.decending])
    .exec()
```

```kotlin
let documents = ditto.store
    .collection("your_collection_name")
    .find([query], [arguments])
    .sort([field], [.Ascending|.Decending])
    .exec()
```

```javascript
const documents = await ditto.store
  .collection("your_collection_name")
  .find([query], [arguments])
  .sort([field], [ascending|decending])
  .exec()
```

```java
List<DittoDocument> documents = ditto.store
  .collection("your_collection_name")
  .find([query], [arguments])
  .sort([field], [ascending|decending])
  .exec();
```

```csharp
var documents = ditto.Store
  .Collection("your_collection_name")
  .Find([query], [arguments])
  .Sort([field], [ascending|decending])
  .Exec();
```

```cpp
std::vector<Document> documents = ditto.get_store()
  .collection("your_collection_name")
  .find([query], [arguments])
  .sort([field], [ascending|decending])
```

```rust
let documents = collection
  .find([query])
  .sort([field], [ascending|decending])
  .exec()?;
```
:::

The following snippet demonstrates a `sort` operation on the `miles` field with results arranged in `ascending` order:

:::CodeblockTabs
```swift
let documents = ditto.store
    .collection("cars")
    .find("color == 'blue'")
    .sort("miles", direction: .ascending)
    .exec()
```

```kotlin
val sortedRedCars = ditto.store.collection("cars")
    .find("color == 'blue'")
    .sort("miles", DittoSortDirection.Ascending)
    .exec()
```

```javascript
const documents = await ditto.store
  .collection("cars")
  .find("color == 'blue'")
  .sort("miles", direction: .ascending)
  .exec()
```

```java
List<DittoDocument> documents = ditto.store
  .collection("cars")
  .find("color == 'blue'")
  .sort("miles", DittoSortDirection.Ascending)
  .exec();
```

```csharp
var documents = ditto.Store
  .Collection("cars")
  .Find("color == 'blue'")
  .Sort("miles", DittoSortDirection.Ascending)
  .Exec();
```

```cpp
std::vector<Document> documents = ditto.get_store()
  .collection("cars")
  .find("color == 'blue'")
  .sort("miles", "ascending");
```

```rust
let sort_param = ffi_sdk::COrderByParam {
    query_c_str: c!("miles"),
    direction: ffi_sdk::QuerySortDirection::Ascending,
};

let documents = collection
  .find("color == \'blue\'")
  .sort(sort_param)
  .exec()?;
```
:::

### Limit and Sort Methods in a Single Executable

To enhance query efficiency, you can perform both `sort` and `limit` operations within a single query, as follows:

:::CodeblockTabs
```swift
let documents = ditto.store
  .collection("cars")
  .find("color == 'blue'")
  .sort("miles", direction: .ascending)
  .limit(100)
  .exec()
```

```kotlin
val documents = ditto.store
    .collection("cars")
    .find("color == 'blue'")
    .sort("miles", DittoSortDirection.Ascending)
    .limit(100)
    .exec()
```

```javascript
const documents = await ditto.store
  .collection("cars")
  .find("color == 'blue'")
  .sort("miles", "ascending")
  .limit(100)
  .exec()
```

```java
List<DittoDocument> documents = ditto.store
  .collection("cars")
  .find("color == 'blue'")
  .sort("miles", DittoSortDirection.Ascending)
  .limit(100)
  .exec();
```

```csharp
var documents = ditto.Store
  .Collection("cars")
  .Find("color == 'blue'")
  .Sort("miles", "ascending")
  .Limit(100)
  .Exec();
```

```cpp
std::vector<Document> documents = ditto.get_store()
  .collection("cars")
  .find("color == 'blue'")
  .sort("miles", "ascending")
  .limit(100);
```

```rust
let sort_param = ffi_sdk::COrderByParam {
    query_c_str: c!("miles"),
    direction: ffi_sdk::QuerySortDirection::Ascending,
};

let documents = collection
  .find("color == \'blue\'")
  .sort(sort_param)
  .limit(100)
  .exec()?;
```
:::

# Observe Local Method

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.&#x20;

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](docId\:T97K1AzahHrwQrQTZtZHQ) and [Time-Based Replication](docId\:KT8y44UQmtDJXU5yV2_kK).

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.&#x20;

:::CodeblockTabs
```swift
let liveQuery = ditto.store
    .collection("your_collection_name")
    .find(query, arguments)
    .observeLocal { callback }
```

```kotlin
val liveQuery = ditto.store
    .collection("your_collection_name")
    .find([query], [arguments])
    .observeLocal{[callback]}
```

```javascript
const liveQuery = ditto.store
  .collection('your_collection_name')
  .find(your_query)
  .observeLocal((result, event) => {
    // do something with the result
  });
```

```java
DittoLiveQuery liveQuery = ditto.store
    .collection("your_collection_name")
    .find(query, arguments)
    .observeLocal(callback);
```

```csharp
var liveQuery = ditto.Store
  .Collection("your_collection_name")
  .Find([query], [arguments])
  .ObserveLocal([callback]);
```

```cpp
const liveQuery = ditto.get_store()
  .collection("your_collection_name")
  .find([query], [arguments])
  .observe_local([callback])
```

```rust
let liveQuery = collection
  .find([query], [arguments])
  .observe_local([callback])
```
:::

## Creating Live Queries

To set up a single live query, as demonstrated in the following snippet:&#x20;

:::hint{type="info"}
For instructions on creating multiple live queries stored in a single `LiveQuery` object, see [Creating a Batch of Live Queries](./#creating-a-batch-of-live-queries).
:::

1. In the top-most scope of your app, declare a Live Query object.

2. Specify the event you're interested in watching; for example, the `cars` collection where the `color` is `black`.

3. Using the Observe Local method, define the subsequent liveQuery callback function that you want Ditto to execute in your app.&#x20;

   For more information, see [Constructing Live Query Callback Functions](./#constructing-live-query-callback-functions), as follows.

:::CodeblockTabs
```swift
// --- Action somewhere in your application
func userDidInsertCar() {
    _ = try? ditto.store.collection("cars").upsert([
        "model": "Ford",
        "color": "black"
    ] as [String: Any?])
}

// Register live query to update UI
let liveQuery = ditto.store.collection("cars").find("color == 'red'")
    .observeLocal { cars, event in
        // do something
    }
```

```kotlin
// --- Action somewhere in your application
fun userDidInsertCar() {
    ditto.store.collection("cars").upsert(mapOf(
        "model" to "Ford",
        "color" to "black"
    ))
}

// --- DittoRegister live query to update UI
val observeLocalQuery = ditto.store.collection("cars")
    .find("isSold == false")
    .observeLocal { docs, event ->
    // Do something...
}
```

```javascript
const liveQuery = ditto.store
  .collection('cars')
  .find("color == 'red'")
  .observeLocal((cars, event) => {
    // do something
  })
```

```java
// --- Action somewhere in your application
Map<String, Object> content = new HashMap<>();
content.put("model", "Ford");
content.put("color", "black");
ditto.store.collection("cars").upsert(content);

// --- Register live query to update UI
DittoLiveQuery liveQueryLocal = ditto.store.collection("cars")
        .find("owner == 'Susan'")
        .observeLocal((docs, event) -> {
            // Do something...
        });
```

```csharp
var liveQuery = ditto.Store
  .Collection("your_collection_name")
  .Find([query], [arguments])
  .ObserveLocal([callback]);
```

```cpp
// --- Register live query to update UI
std::shared_ptr<LiveQuery> query =
    collection.find("color == 'red'")
        .observe_local([&](std::vector<Document> docs, LiveQueryEvent event) {

        });
```

```rust
let liveQuery = collection
  .find("color == \'black\'")
  .observe_local(move |docs, event| {
    // print the number of blue cars
    println!(docs.len());
  }
```
:::

For example, the following snippet demonstrates an `observeLocal` method that monitors changes in the `cars` collection where the `color` is `"blue"`.&#x20;

Once the changes occur, the total number of documents displays to the end user.

:::CodeblockTabs
```swift
```

```kotlin
```

```javascript
```

```java
DittoLiveQuery liveQuery = ditto.store
  .collection("cars")
  .find("color == 'blue'")
  .observeLocal((docs, event) -> {
    // log the number of blue cars
    Log.v(docs.length)
  })
```

```csharp
```

```cpp
```

```rust
```
:::

## Constructing Live Query Callback Functions

If you're *not&#x20;*&#x75;sing 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.

:::hint{type="info"}
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.&#x20;

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](https://react.dev/learn).
:::

### Events Argument

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.&#x20;

The following table provides an overview of events in Ditto:

| **Event Type** | **Description**                                                                                                                                                                                                                                                                                                                                  |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Initial`      | The first event that will be delivered (and delivered only once).                                                                                                                                                                                                                                                                                |
| `Update`       | The event to return each time the results of your live query change.<br /><br />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. |

## Creating a Batch of Live Queries

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.

:::hint{type="info"}
For more information about batching live queries, see `LiveQueryEvent` in the [SDK Setup Guides](docId\:Eaz0KkFOztspuhjJA5sNj) > Ditto API reference for your language. (For a complete listing, see [Directory of Ditto Technical Documentation](docId\:oxv2ZQ7x15T1k8SL_ZTPK).)
:::

For more information about Ditto `arrays` and `maps`, see [Data Types](docId\:yxemKH1COm3CSUuMqcnlf).

## Canceling Live Queries

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.

:::CodeblockTabs
Swift pseudocode

```swift
// subscription = nil // this does not work
sub.cancel() // this is correct!
```
:::

:::CodeblockTabs
Swift pseudocode

```swift
// subscriptions.removeAll() Do not do this <- this will not work

for sub in subscriptions {
   sub.cancel()
}

subscriptions.removeAll() // After calling cancel, it is safe to remove them from the array.
```
:::

