Skip to content

FieldDsl

interface FieldDsl

Operators to construct MongoDB field references from Kotlin code.

Example

class User(
    val name: String,
    val age: Int,
    val profile: Profile,
)

class Profile(
    val id: ObjectId,
    val friends: List<ObjectId>,
)

with(FieldDsl(users.context)) {
    // 'name'
    User::name

    // 'age'
    User::age

    // 'profile.id'
    User::profile / Profile::id

    // 'profile.friends'
    User::profile / Profile::friends
}

In most situations, an instance of this interface should be provided in all operations that require it.

Inheritors

Constructors

FieldDsl

fun FieldDsl(context: BsonContext): FieldDsl

Creates an instance of FieldDsl.

In most situations, users shouldn't need to call this method, as an instance is often provided by operations:

users.find {
    // the 'this' receiver already implements the [FieldDsl] interface.
}

However, in some cases you may want to create fields outside operations. You can do so with:

with(FieldDsl(users.context)) {
    User::profile / Profile::name
}

Properties

context

@LowLevelApi



abstract val context: PropertyNameStrategy

The strategy used when converting from KProperty1 to Field.

field

Converts a Kotlin property into a Field.

The KtMongo DSL is built on top of the Field interface, which represents a specific field in a document (possibly nested).

To help with writing requests, we provide utilities to use Kotlin property references as well:

class User(
    val name: String,
    val age: Int,
)

println(User::name)       // KProperty1…
println(User::name.field) // Field 'name'

Most functions of the DSL have an overload that accepts a KProperty1 and calls field before calling the real operator implementation.

Functions

div

open operator fun <Root, Type, Child> Field<Root, Type>.div(child: Field<Type, Child>): Field<Root, Child>

Refers to child as a nested field of the current field.

Examples
class User(
    val id: Int,
    val profile: Profile,
)

class Profile(
    val name: String,
    val age: Int,
)

// Refer to the name
println(User::profile / Profile::name)
// → 'profile.name'

// Refer to the age
println(User::profile / Profile::age)
// → 'profile.age'

See also

open operator fun <Root, Type, Child> Field<Root, Type>.div(child: KProperty1<in Type & Any, Child>): Field<Root, Child>

Refers to child as a nested field of the current field.

Examples
class User(
    val id: Int,
    val profile: Profile,
)

class Profile(
    val name: String,
    val age: Int,
)

// Refer to the name
println(User::profile / Profile::name)
// → 'profile.name'

// Refer to the age
println(User::profile / Profile::age)
// → 'profile.age'

See also

open operator fun <Root, Parent, Child> KProperty1<Root, Parent>.div(child: KProperty1<Parent & Any, Child>): Field<Root, Child>

Refers to child as a nested field of the current field.

Examples
class User(
    val id: Int,
    val profile: Profile,
)

class Profile(
    val name: String,
    val age: Int,
)

// Refer to the id
println(User::id)
// → 'id'

// Refer to the name
println(User::profile / Profile::name)
// → 'profile.name'

// Refer to the age
println(User::profile / Profile::age)
// → 'profile.age'

See also

get

open operator fun <Root, Type> Field<Root, Collection<Type>>.get(index: Int): Field<Root, Type>

Refers to a specific item in an array, by its index.

Examples
class User(
    val name: String,
    val friends: List<Friend>,
)

class Friend(
    val name: String,
)

// Refer to the first friend
println(User::friends[0])
// → 'friends.$0'

// Refer to the third friend's name
println(User::friends[2] / Friend::name)
// → 'friends.$2.name'
open operator fun <Root, Type> KProperty1<Root, Collection<Type>>.get(index: Int): Field<Root, Type>

Refers to a specific item in an array, by its index.

Examples
class User(
    val name: String,
    val friends: List<Friend>,
)

class Friend(
    val name: String,
)

// Refer to the first friend
println(User::friends[0])
// → 'friends.$0'

// Refer to the third friend's name
println(User::friends[2] / Friend::name)
// → 'friends.$2.name'
open operator fun <Root, Type> Field<Root, Map<String, Type>>.get(key: String): Field<Root, Type>

Refers to a specific item in a map, by its name.

Examples
class User(
    val name: String,
    val friends: Map<String, Friend>,
)

class Friend(
    val name: String,
)

// Refer to the friend Bob
println(User::friends["bob"])
// → 'friends.bob'

// Refer to Bob's name
println(User::friends["bob"] / Friend::name)
// → 'friends.bob.name'
open operator fun <Root, Type> KProperty1<Root, Map<String, Type>>.get(index: String): Field<Root, Type>

Refers to a specific item in a map, by its name.

Examples
class User(
    val name: String,
    val friends: Map<String, Friend>,
)

class Friend(
    val name: String,
)

// Refer to the friend Bob
println(User::friends["bob"])
// → 'friends.bob'

// Refer to Bob's name
println(User::friends["bob"] / Friend::name)
// → 'friends.bob.name'

unsafe

open infix fun <Root, Type, Child> Field<Root, Type>.unsafe(child: String): Field<Root, Child>

Refers to a field child of the current field, with no compile-time safety.

Sometimes, we must refer to a field that we don't want to add in the DTO representation. For example, when writing complex aggregation queries that use intermediary fields that are removed before the data is sent to the server.

We recommend preferring the type-safe syntax when possible (see Field).

Example
println(User::profile.unsafe<Int>("age")) // 'profile.age'

See also

open infix fun <Root, Child> KProperty1<Root, *>.unsafe(child: String): Field<Root, Child>

Refers to a field child of the current field, with no compile-time safety.

Sometimes, we must refer to a field that we don't want to add in the DTO representation. For example, when writing complex aggregation queries that use intermediary fields that are removed before the data is sent to the server.

We recommend preferring the type-safe syntax when possible (see Field).

Example
println(User::profile.unsafe<Int>("age")) // 'profile.age'

See also

open infix fun <Root, Child> Field<Root, *>.unsafe(child: Field<*, Child>): Field<Root, Child>

Refers to a field child of the current field, without checking that it is a field available on the current object.

We recommend preferring the type-safe syntax when possible (see Field).

Example
println(User::profile / Pet::name)       // ⚠ compilation error: 'profile' doesn't have the type 'Pet'
println(User::profile unsafe Pet::name)  // 'profile.name'

See also

open infix fun <Root, Child> Field<Root, *>.unsafe(child: KProperty1<*, Child>): Field<Root, Child>

Refers to a field child of the current field, without checking that it is a field available on the current object.

We recommend preferring the type-safe syntax when possible (see Field).

Example
println(User::profile / Pet::name)       // ⚠ compilation error: 'profile' doesn't have the type 'Pet'
println(User::profile unsafe Pet::name)  // 'profile.name'

See also

open infix fun <Root, Child> KProperty1<Root, *>.unsafe(child: Field<*, Child>): Field<Root, Child>

Refers to a field child of the current field, without checking that it is a field available on the current object.

We recommend preferring the type-safe syntax when possible (see Field).

Example
println(User::profile / Pet::name)       // ⚠ compilation error: 'profile' doesn't have the type 'Pet'
println(User::profile unsafe Pet::name)  // 'profile.name'

See also

open infix fun <Root, Child> KProperty1<Root, *>.unsafe(child: KProperty1<*, Child>): Field<Root, Child>

Refers to a field child of the current field, without checking that it is a field available on the current object.

We recommend preferring the type-safe syntax when possible (see Field).

Example
println(User::profile / Pet::name)       // ⚠ compilation error: 'profile' doesn't have the type 'Pet'
println(User::profile unsafe Pet::name)  // 'profile.name'

See also