---
title: READ
slug: v4-5/crud-read
description: crud-read
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.

- [Single Execution Queries](./#single-execution-queries)
- [Store Observer Queries](./#store-observer-queries)

# Single Execution Queries

To perform a single execution query on the Ditto store, call the `execute` API method on the `store` namespace as follows:

:::CodeblockTabs
```swift
let result = await ditto.store.execute(query: "SELECT * FROM cars")
```

```kotlin
val result = ditto.store.execute("SELECT * FROM cars")
```

```javascript
const result = await ditto.store.execute("SELECT * FROM cars");
```

```java
DittoQueryResult result = (DittoQueryResult) ditto.store.execute(
    "SELECT * FROM cars",
    new Continuation<>() {
        @NonNull
        @Override
        public CoroutineContext getContext() {
            return EmptyCoroutineContext.INSTANCE;
        }

        @Override
        public void resumeWith(@NonNull Object o) {
            if (o instanceof Result.Failure) {
                // Handle failure
            }
        }
    }
);
```

```csharp
var result = await ditto.Store.ExecuteAsync("SELECT * FROM cars");
```

```cpp
auto result = ditto.get_store().execute("SELECT * FROM cars").get();
```

```rust
let result = ditto.store().execute("SELECT * FROM cars", None);
```
:::

## Using args to Query Dynamic Values

When dealing with data that may change dynamically during runtime, instead of defining the changing values directly in the query `string`, encapsulate them in a top-level `args` object you can use to reference the values in your queries.&#x20;

To pass an argument to the `execute` function, use the `:[argument]` syntax with DQL where the `[argument]` maps to the field in the provided `args` object.&#x20;

:::::VerticalSplit{layout="right"}
::::VerticalSplitItem
:::CodeblockTabs
```swift
let result = await ditto.store.execute(
  query: "SELECT * FROM cars WHERE color = :color",
  arguments: [ "color": "blue" ])
```

```kotlin
val result = ditto.store.execute(
  "SELECT * FROM cars WHERE color = :color",
  mapOf("color" to "blue"))
```

```javascript
const result = await ditto.store.execute(
  "SELECT * FROM cars WHERE color = :color",
  { color: "blue" });
```

```java
DittoQueryResult result = (DittoQueryResult) ditto.store.execute(
    "SELECT * FROM cars WHERE color = :color",
    Collections.singletonMap("color", "blue"),
    new Continuation<>() {
        @NonNull
        @Override
        public CoroutineContext getContext() {
            return EmptyCoroutineContext.INSTANCE;
        }

        @Override
        public void resumeWith(@NonNull Object o) {
            if (o instanceof Result.Failure) {
                // Handle failure
            }
        }
    }
);
```

```csharp
const result = await ditto.Store.ExecuteAsync(
  "SELECT * FROM cars WHERE color = :color",
  new Dictionary<string, object> { "color", "blue" });
```

```cpp
auto result = ditto.get_store().execute(
  "SELECT * FROM cars WHERE color = :color",
  {{"color", "blue"}}).get();
```

```rust
struct Args {
    color: String,
}

//...

let args = Args {
    color: "blue".to_string(),
};

let result = ditto.store().execute(
  "SELECT * FROM cars WHERE color = :color",
  Some(args.into()));
```
:::
::::

:::VerticalSplitItem
For example, here `color` is passed as an argument to the `execute` function, and, within the query string, `:color` placeholder references the `color` defined in a top-level `args` object.&#x20;
:::
:::::

Once the previous example operation executes, the query becomes `SELECT * FROM cars WHERE color = blue`.&#x20;

## Managing Query Results

After executing a query, the `result` object that is returned includes both the overall content retrieved and individual items. Each item is encapsulated in independent `QueryResultItem` objects that you can use to access them either directly or as raw CBOR or JSON data.&#x20;

Rather than retrieving the items as part of the query execution and making them available immediately after execution, each item is *lazy loaded*. Lazy loading involves postponing fetching and storing in memory until requested on-demand or accessed later.

Here is an example query execution to select all documents from the `cars` collection. The result is stored in the variable result. Then, each item is lazy loaded from the result object and stored in the `items`:

:::CodeblockTabs
```swift
let result = await ditto.store.execute(query: "SELECT * FROM cars")

let items = result.items
```

```kotlin
val result = ditto.store.execute("SELECT * FROM cars")

const items = result.items
```

```javascript
const result = await ditto.store.execute("SELECT * FROM cars")

const items = result.items
```

```java
DittoQueryResult result = (DittoQueryResult) ditto.store.execute(
    "SELECT * FROM cars",
    new Continuation<>() {
        @NonNull
        @Override
        public CoroutineContext getContext() {
            return EmptyCoroutineContext.INSTANCE;
        }

        @Override
        public void resumeWith(@NonNull Object o) {
            if (o instanceof Result.Failure) {
                // Handle failure
            }
        }
    }
);

DittoQueryResultItems items = result.items;
```

```csharp
var result = await ditto.Store.ExecuteAsync("SELECT * FROM cars");

var items = result.Items;
```

```cpp
auto result = ditto.get_store().execute("SELECT * FROM cars").get();

auto items = result.items();
```

```rust
let result = ditto.store().execute("SELECT * FROM cars", None);

let items = result.items();
```
:::

## Working with a QueryResultItem

The result `items` object is a collection of`QueryResultItem`. Each item's value can be independently managed to meet the needs of your scenario.

### Value

To retrieve the value, call the `value` property on an item:&#x20;

:::CodeblockTabs
```swift
let result = await ditto.store.execute(query: "SELECT * FROM cars")

let item = result.items[0]
let itemValue = item.value
let itemValueColor = item.value["color"]
```

```kotlin
val result = ditto.store.execute("SELECT * FROM cars")

val item = result.items.first()
val itemValue = item.value
val itemValueColor = item.value["color"]
```

```javascript
const result = await ditto.store.execute(`SELECT * FROM cars`)

const item = result.items[0]
const itemValue = item.value
const itemValueColor = item.value["color"]
```

```java
DittoQueryResult result = (DittoQueryResult) ditto.store.execute(
    "SELECT * FROM cars",
    new Continuation<>() {
        @NonNull
        @Override
        public CoroutineContext getContext() {
            return EmptyCoroutineContext.INSTANCE;
        }

        @Override
        public void resumeWith(@NonNull Object o) {
            if (o instanceof Result.Failure) {
                // Handle failure
            }
        }
    }
);

DittoQueryResultItem item = result.items[0]
Map<String, Object> itemValue = item.value
String itemValueColor = item.value["color"].toString()
```

```csharp
var result = await ditto.Store.ExecuteAsync("SELECT * FROM cars");

var item = result.Items[0];
var itemValue = item.Value;
var itemValueColor = item.Value["color"] as string;
```

```cpp
// use json or cbor value
```

```rust
let result = ditto.store().execute("SELECT * FROM cars", None);

let item = result.items(0);
let itemValue = item.materialize();
```
:::

### Materializing the Value

To help manage memory usage more efficiently, content associated with an `item` is lazily loaded, meaning it materializes — loads into memory — only upon the initial call to `value`.&#x20;

To load the item's value into memory, use any of the following methods as appropriate:

:::CodeblockTabs
```swift
// Returns `true` if value is currently held materialized in memory, otherwise returns `false`
item.isMaterialized

// Loads the item's value into memory
item.materialize()

// Release item's value from memory
item.dematerialize()
```

```kotlin
// Returns `true` if value is currently held materialized in memory, otherwise returns `false`
item.isMaterialized

// Loads the item's value into memory
item.materialize()

// Release item's value from memory
item.dematerialize()
```

```javascript
// Returns `true` if value is currently held materialized in memory, otherwise returns `false`
item.isMaterialized

// Loads the item's value into memory
item.materialize()

// Release item's value from memory
item.dematerialize()
```

```java
// Returns `true` if value is currently held materialized in memory, otherwise returns `false`
item.isMaterialized

// Loads the item's value into memory
item.materialize()

// Release item's value from memory
item.dematerialize()
```

```csharp
// Returns `true` if value is currently held materialized in memory, otherwise returns `false`
item.IsMaterialized;

// Loads the item's value into memory
item.Materialize();

// Release item's value from memory
item.Dematerialize();
```

```cpp
// Not Supported
```

```rust
// Loads the item's value into memory
item.materialize();
```
:::

### Raw CBOR Value

To access the result items as CBOR data:

:::hint{type="info"}
The result of this method call is not cached.
:::

:::CodeblockTabs
```swift
let result = await ditto.store.execute(query: "SELECT * FROM cars")

let cborSerializedItem = result.items[0].cborData()
```

```kotlin
val result = ditto.store.execute("SELECT * FROM cars")

val cborItem = result.items.first().cborData()
```

```javascript
const result = await ditto.store.execute(`SELECT * FROM cars`)

const cborItem = result.items[0].cborData()
```

```java
DittoQueryResult result = (DittoQueryResult) ditto.store.execute(
    "SELECT * FROM cars",
    new Continuation<>() {
        @NonNull
        @Override
        public CoroutineContext getContext() {
            return EmptyCoroutineContext.INSTANCE;
        }

        @Override
        public void resumeWith(@NonNull Object o) {
            if (o instanceof Result.Failure) {
                // Handle failure
            }
        }
    }
);

byte[] cborItem = result.items[0].cborData()
```

```csharp
var result = await ditto.Store.ExecuteAsync("SELECT * FROM cars");

var cborItem = result.Items[0].CborData();
```

```cpp
auto result = ditto.get_store().execute("SELECT * FROM cars").get();

auto cborItem = result.get_item(0).cbor();
```

```rust
let result = ditto.store().execute("SELECT * FROM cars", None);

let cborItem = result.items(0).cbor();
```
:::

### Raw JSON Value

To access the result items as a JSON-string:

:::hint{type="info"}
The result of this method call is not cached.
:::

:::CodeblockTabs
```swift
let result = await ditto.store.execute(query: "SELECT * FROM cars")

let jsonSerializedItem: String = result.items[0].jsonString()

let jsonAsData: Data = Data(jsonSerializedItem.utf8)
```

```kotlin
val result = ditto.store.execute("SELECT * FROM cars")

val jsonItem = result.items.first().jsonString()
```

```javascript
const result = await ditto.store.execute(`SELECT * FROM cars`)

const jsonItem = result.items[0].jsonString()
```

```java
DittoQueryResult result = (DittoQueryResult) ditto.store.execute(
    "SELECT * FROM cars",
    Collections.singletonMap("color", "blue"),
    new Continuation<>() {
        @NonNull
        @Override
        public CoroutineContext getContext() {
            return EmptyCoroutineContext.INSTANCE;
        }

        @Override
        public void resumeWith(@NonNull Object o) {
            if (o instanceof Result.Failure) {
                // Handle failure
            }
        }
    }
);

String cborItem = result.items[0].jsonData()
```

```csharp
var result = await ditto.Store.ExecuteAsync("SELECT * FROM cars");

var jsonItem = result.Items[0].JsonString();
```

```cpp
auto result = ditto.get_store().execute("SELECT * FROM cars").get();

auto jsonItem = result.get_item(0).json();
```

```rust
let result = ditto.store().execute("SELECT * FROM cars", None);

let jsonItem = result.items(0).json();
```
:::

# Store Observer Queries

A *store observer* is a DQL query that runs continuously and triggers a callback when a change to the store impacts the results of the query.&#x20;

Store observers are useful when you want to monitor changes from your local Ditto store and react to them immediately. For instance, when your end user updates their profile, you can asynchronously display the changes to the end user in realtime.

:::CodeblockTabs
```swift
let observer = ditto.store.registerObserver(
  query: "SELECT * FROM cars"){ result in /* handle change */ };
```

```kotlin
val observer = ditto.store.registerObserver("SELECT * FROM cars") { result ->
  /* handle change */ };
```

```javascript
const changeHandler = (result) => {
  // handle change
}
const observer = ditto.store.registerObserver(
  "SELECT * FROM cars",
  changeHandler);
```

```java
DittoStoreObserver observer = ditto.store.registerObserver(
    "SELECT * FROM cars",
    result -> {
        // handle change
    }
);
```

```csharp
// Without Arguments
var result = await ditto.Store.RegisterObserver(
  "SELECT * FROM cars",
  (result) => {
    // handle change
  });

// With Arguments
var result = ditto.Store.RegisterObserver(
  "SELECT * FROM cars",
  (result) => {
    // handle change
  });

```

```cpp
auto observer = ditto.get_store().register_observer(
  "SELECT * FROM cars",
  [&](QueryResult result) { /* handle change */ });
```

```rust
let observer = ditto.store().register_observer(
  "SELECT * from cars",
  None,
  move |result: QueryResult| {
    // handle change
  })
```
:::

## Store Observer with Arguments

:::CodeblockTabs
```swift
let observer = ditto.store.registerObserver(
  query: "SELECT * FROM cars WHERE color = :color",
  argumets: [ "color": "blue" ]){ result in /* handle change */ };
```

```kotlin
ditto.store.registerObserver(
  "SELECT * FROM cars WHERE color = :color",
  mapOf("color" to "blue")) { result ->
  /* handle change */ };
```

```javascript
const changeHandler = (result) => {
  // handle change
}
const observer = ditto.store.registerObserver(
  "SELECT * FROM cars WHERE color = :color",
  changeHandler,
  { color: 'blue' });
```

```java
DittoStoreObserver observer = ditto.store.registerObserver(
    "SELECT * FROM cars WHERE color = :color",
    Collections.singletonMap("color", "blue"),
    result -> {
        // handle change
    }
);
```

```csharp
// Without Arguments
var result = await ditto.Store.RegisterObserver(
  "SELECT * FROM cars",
  (result) => {
    // handle change
  });

// With Arguments
var result = ditto.Store.RegisterObserver(
  "SELECT * FROM cars WHERE color = :color",
  new Dictionary<string, object> { "color", "blue" },
  (result) => {
    // handle change
  });

```

```cpp
auto observer = ditto.get_store().register_observer(
  "SELECT * FROM cars",
  {{"color", "blue"}}),
  [&](QueryResult result) { /* handle change */ });
```

```rust
struct Args {
    color: String,
}

//...

let args = Args {
    color: "blue".to_string(),
}

let observer = ditto.store().register_observer(
  "SELECT * from cars WHERE color = :color",
  args,
  move |result: QueryResult| {
    // handle change
  })
```
:::

## Canceling a Store Observer

To cancel a store observer, call `cancel` on the observer object.

Once canceled, the store observer will stop processing in the background and will no longer call the provided callback.

:::CodeblockTabs
```swift
observer.cancel()
```

```kotlin
observer.cancel()
```

```javascript
observer.cancel()
```

```java
observer.cancel();
```

```csharp
observer.Cancel()
```

```cpp
observer.cancel();
```

```rust
observer.cancel()
```
:::

## Accessing Store Observers

To access store observers from the local Ditto store:

:::CodeblockTabs
```swift
ditto.store.observers
```

```kotlin
ditto.store.observers
```

```javascript
ditto.store.observers
```

```java
ditto.store.observers;
```

```csharp
ditto.Store.Observers
```

```cpp
ditto.get_store().observers()
```

```rust
ditto.store().observers()
```
:::

