# Query builders

The fluent query builders, expression helpers, and surql DSL of the SurrealDB Kotlin SDK.

The CRUD methods on [`SurrealClient`](/docs/reference/kotlin/api/core/surreal-client.md) return fluent builders that compile to [SurrealQL](/docs/reference/query-language.md). Each builder is refined with chainable methods and terminated with [`await()`](#await) (raw [`JsonElement`](/docs/reference/kotlin/api/values/value.md)) or the typed [`awaitAs<T>()`](#await-as) extension.

**Source:** [surrealdb.kotlin](https://github.com/surrealdb/surrealdb.kotlin)

```kotlin title="Import"
import com.surrealdb.kotlin.query.awaitAs
import com.surrealdb.kotlin.query.field
import com.surrealdb.kotlin.query.gte
```

---

## Terminal methods

### `.await()` {#await}

Executes the builder and returns the unwrapped result of the first statement as a [`JsonElement`](/docs/reference/kotlin/api/values/value.md).

```kotlin title="Method Syntax"
builder.await()
```

**Returns:** `JsonElement`

### `.awaitRaw()` {#await-raw}

Executes the builder and returns the raw `[{ status, result, time, type }]` response envelope.

```kotlin title="Method Syntax"
builder.awaitRaw()
```

**Returns:** `JsonElement`

### `.awaitAs<T>()` {#await-as}

An inline extension that executes the builder and decodes the result into `T` using [`kotlinx.serialization`](/docs/reference/kotlin/concepts/serialization.md). Available on every builder.

```kotlin title="Method Syntax"
builder.awaitAs<T>()
```

**Returns:** `T`

```kotlin title="Example"
val people: List<Person> = client.select(Table("person")).awaitAs()
```

### `.compile()` {#compile}

Compiles the builder to a `BoundQuery` without executing it - useful for inspection or composing with [`.query()`](/docs/reference/kotlin/api/core/surreal-client.md#query).

```kotlin title="Method Syntax"
builder.compile()
```

**Returns:** `BoundQuery`

---

## `SelectQuery` {#select-query}

Returned by [`.select(what)`](/docs/reference/kotlin/api/core/surreal-client.md#select).

<table>
    <thead>
        <tr><th>Method</th><th>Description</th></tr>
    </thead>
    <tbody>
        <tr><td id="fields"><code>.fields(vararg names)</code></td><td>Selects specific fields.</td></tr>
        <tr><td><code>.value(field)</code></td><td>Selects a single field's value.</td></tr>
        <tr><td id="where"><code>.where(expr)</code></td><td>Filters with an <a href="#expressions">expression</a>.</td></tr>
        <tr><td id="start"><code>.start(n)</code></td><td>Skips the first <code>n</code> records.</td></tr>
        <tr><td id="limit"><code>.limit(n)</code></td><td>Limits the number of records.</td></tr>
        <tr><td id="fetch"><code>.fetch(vararg fields)</code></td><td>Fetches related records.</td></tr>
        <tr><td><code>.timeout(seconds)</code></td><td>Sets a query timeout.</td></tr>
        <tr><td><code>.version(literal)</code></td><td>Reads at a specific version.</td></tr>
    </tbody>
</table>

```kotlin title="Example"
val adults: List<Person> = client
    .select(Table("person"))
    .where(field("age") gte 18)
    .limit(50)
    .awaitAs()
```

## Content builders

[`CreateQuery`](/docs/reference/kotlin/api/core/surreal-client.md#create), [`UpdateQuery`](/docs/reference/kotlin/api/core/surreal-client.md#update), [`UpsertQuery`](/docs/reference/kotlin/api/core/surreal-client.md#upsert), and [`RelateQuery`](/docs/reference/kotlin/api/core/surreal-client.md#relate) accept content and a return mode.

<table>
    <thead>
        <tr><th>Method</th><th>Description</th></tr>
    </thead>
    <tbody>
        <tr><td><code>.content(data)</code></td><td>Sets the record content (a <code>JsonElement</code>).</td></tr>
        <tr><td><code>.where(expr)</code></td><td>Filters affected records (update, upsert, merge, patch, delete).</td></tr>
        <tr><td id="return-mode"><code>.returnMode(mode)</code></td><td>Controls the returned payload (see <a href="#return-mode-type">ReturnMode</a>).</td></tr>
    </tbody>
</table>

## `ReturnMode` {#return-mode-type}

```kotlin title="Import"
import com.surrealdb.kotlin.query.ReturnMode
```

<table>
    <thead>
        <tr><th>Value</th><th>Description</th></tr>
    </thead>
    <tbody>
        <tr><td><code>ReturnMode.None</code></td><td>Returns nothing.</td></tr>
        <tr><td><code>ReturnMode.Before</code></td><td>Returns records as they were before the change.</td></tr>
        <tr><td><code>ReturnMode.After</code></td><td>Returns records after the change.</td></tr>
        <tr><td><code>ReturnMode.Diff</code></td><td>Returns a JSON Patch diff.</td></tr>
        <tr><td><code>ReturnMode.Fields(names)</code></td><td>Returns only the named fields.</td></tr>
    </tbody>
</table>

## `RunQuery` {#run-query}

Returned by [`.run(function)`](/docs/reference/kotlin/api/core/surreal-client.md#run).

<table>
    <thead>
        <tr><th>Method</th><th>Description</th></tr>
    </thead>
    <tbody>
        <tr><td><code>.args(vararg args)</code></td><td>Sets the function arguments.</td></tr>
        <tr><td><code>.version(version)</code></td><td>Selects a function version.</td></tr>
    </tbody>
</table>

---

## Expression helpers {#expressions}

Build `WHERE` expressions with the helper functions and infix operators from `com.surrealdb.kotlin.query`.

```kotlin title="Import"
import com.surrealdb.kotlin.query.field
import com.surrealdb.kotlin.query.value
import com.surrealdb.kotlin.query.gte
import com.surrealdb.kotlin.query.and
```

<table>
    <thead>
        <tr><th>Helper</th><th>SurrealQL</th></tr>
    </thead>
    <tbody>
        <tr><td><code>field(name)</code></td><td>A validated field reference.</td></tr>
        <tr><td><code>value(any)</code></td><td>A literal value.</td></tr>
        <tr><td><code>raw(boundQuery)</code></td><td>A raw fragment.</td></tr>
        <tr><td><code>a eq b</code></td><td><code>=</code></td></tr>
        <tr><td><code>a neq b</code></td><td><code>!=</code></td></tr>
        <tr><td><code>a lt b</code></td><td><code>&lt;</code></td></tr>
        <tr><td><code>a lte b</code></td><td><code>&lt;=</code></td></tr>
        <tr><td><code>a gt b</code></td><td><code>&gt;</code></td></tr>
        <tr><td><code>a gte b</code></td><td><code>&gt;=</code></td></tr>
        <tr><td><code>a contains b</code></td><td><code>CONTAINS</code></td></tr>
        <tr><td><code>a inside b</code></td><td><code>IN</code></td></tr>
        <tr><td><code>a and b</code></td><td><code>AND</code></td></tr>
        <tr><td><code>a or b</code></td><td><code>OR</code></td></tr>
        <tr><td><code>not(expr)</code></td><td><code>!</code></td></tr>
    </tbody>
</table>

> [!NOTE]
> Inequality is `neq` (not `ne`) and membership is `inside` (not `in`, which is a reserved Kotlin keyword).

```kotlin title="Example"
import com.surrealdb.kotlin.query.field
import com.surrealdb.kotlin.query.gte
import com.surrealdb.kotlin.query.eq
import com.surrealdb.kotlin.query.and

val expr = (field("age") gte 18) and (field("active") eq true)
val results = client.select(Table("person")).where(expr).awaitAs<List<Person>>()
```

---

## `surql` DSL {#surql}

The `surql` helpers build a parameterised `BoundQuery` with automatic, injection-safe binding of values and record identifiers.

```kotlin title="Import"
import com.surrealdb.kotlin.query.surql
```

```kotlin title="Example"
// Vararg bindings
val a = surql("SELECT * FROM person WHERE age > \$min", "min" to 25)

// Builder block
val b = surql {
    +"SELECT * FROM person WHERE age > "
    param("min", 25)
}

val result = client.query(a)
```

## Learn more

- [SurrealClient API reference](/docs/reference/kotlin/api/core/surreal-client.md) for the CRUD methods
- [Data manipulation](/docs/reference/kotlin/concepts/data-manipulation.md) for the concepts
- [Serialisation](/docs/reference/kotlin/concepts/serialization.md) for `awaitAs`
