FilterDsl

interface FilterDsl

A DSL interface providing support for "low-level" DynamoDB filter/condition expressions. The methods and properties in this interface create boolean expressions to filter item results (e.g., in Scan or Query operations). Expressions are typically formed by getting a reference to an attribute path via the attr property and then exercising some operation or function upon it.

For example:

filter {
attr["foo"] eq 42
}

This example creates an expression which checks whether an attribute named foo is equal to the value 42.

(Non-)Relationship to schema

The expressions formed by FilterDsl are referred to as "low-level" filter expressions. This is because they are not restricted by or adherent to any defined schema. Instead, they are a DSL convenience layer over literal DynamoDB expression strings and expression attribute value maps. As such they provide minimal type correctness and may allow you to form expressions which are invalid given the shape of your data, such as attributes which don't exist, comparisons with mismatched data types, etc.

Attributes

Every filter condition contains at least one attribute. Attributes are referenced by attribute paths, analogous to document paths in DynamoDB. Attribute paths consist of one or more elements, which are either names (e.g., of a top-level attribute or a nested key in a map attribute) or indices (i.e., into a list). The first (and often only) element of an attribute path is a name.

Getting a top-level attribute

All attribute paths start with a top-level attribute expression, created by the attr function:

attr["foo"] // References the top-level attribute "foo"

Note, the attribute foo may not exist for a given item or for an entire table.

Nesting

Sometimes values are nested inside other attributes like lists and maps. Filter expressions can operate on those nested values by forming a more detailed attribute path using the [] operator or get functions on a path.

For example, consider an item structure such as:

{
"foo": "Hello",
"bar": {
"baz": [
"Yay",
null,
42,
true
]
}
}

The value "Yay" can be referenced with the following DSL syntax:

attr["bar"]["baz"][0]

That is, in the top-level attribute bar, in the value keyed by baz, the element at index 0.

Equalities/inequalities

A very common filter condition is verifying whether some attribute is equal (or unequal) to another value—either a literal value or the value of another attribute. These comparisons are available by using the following functions:

  • eq — checks if two values are equal (equivalent to Kotlin's == operator)

  • neq — checks if two values are not equal (equivalent to Kotlin's != operator)

  • lt — checks if a value is less than another value (equivalent to Kotlin's < operator)

  • lte — checks if a value is less than or equal to another value (equivalent to Kotlin's <= operator)

  • gt — checks if a value is greater than another value (equivalent to Kotlin's > operator)

  • gte — checks if a value is greater than or equal to another value (equivalent to Kotlin's >= operator)

For example:

attr["foo"] eq 5           // Checks whether the value of attribute `foo` is `5`
attr["bar"] gt attr["baz"] // Checks whether the value of attribute `bar` is greater than attribute `baz`

Ranges and sets

Expressions can check whether some attribute value is in a given range or set of possible values. These checks are available via the isBetween or isIn functions:

// Checks whether the value of attribute `foo` is between 40 and 60 (inclusive)
attr["foo"] isIn 40..60

// Checks whether the value of attribute `foo` is either 1, 2, 4, 8, 16, or 32
attr["bar"] isIn setOf(1, 2, 4, 8, 16, 32)

// Checks whether the value of attribute `baz` is between the value of `foo` and the value of `bar`
attr["baz"].isBetween(attr["foo"], attr["bar"])

Boolean logic

The previous sections dealt with singular conditions (e.g., a == b, c in (d, e, f), etc.). But complex queries may involve multiple conditions or negative conditions akin to the boolean operations AND (&&), OR (||, and NOT (!). This logic is available via the and, or, and not functions:

and(
attr["foo"] eq 42,
attr["bar"] neq 42,
)

This block checks for value of the attribute foo equalling 42 and the value of attribute bar not equalling 42. This is logically equivalent to the Kotlin syntax:

(foo == 42 && bar != 42)

These boolean functions can be composed in various ways:

or(
attr["foo"] eq "apple",
and(
attr["bar"] lt attr["baz"],
attr["baz"] gte 42,
),
not(
attr["qux"] in setOf("ready", "set", "go"),
),
)

This complex DSL code checks that at least one of three conditions is met (boolean OR):

  • The value of attribute foo is "apple"

  • The value of attribute bar is less than the value of baz –and– the value of baz is greater/equal to 42

  • The value of attribute qux is not one of "ready", "steady", or "go"

This is logically equivalent to the Kotlin syntax:

(foo == "apple") || (bar < baz && baz >= 42) || qux !in setOf("ready", "steady", "go")

Other functions/properties

Several additional filter expressions are possible via the following methods/properties:

  • contains — Checks if a string/list attribute value contains the given value

  • exists — Checks if any value (including null) exists for an attribute. The low-level DynamoDB function for this is attribute_exists.

  • notExists — Checks if no value is present for an attribute (i.e., the attribute is "undefined" for an item). The low-level DynamoDB function for this is attribute_not_exists.

  • isOfType — Checks if an attribute value is of the given type. The low-level DynamoDB function for this is attribute_type.

  • size — Gets the size of an attribute (e.g., number of elements in list/map/set, the length of a string, etc.)

  • startsWith — Checks if a string attribute value starts with the given value. The low-level DynamoDB function for this is begins_with.

For example:

attr["foo"] contains 13 // Checks whether the value of attribute `foo` contains the value `13`
attr["bar"].exists() // Checks whether any value exists for `bar` (including `null`)

Properties

Link copied to clipboard
abstract val attr: Attr

Accesses an attribute path reference from a top-level attribute name in this filter expression (e.g., attr["foo"] references the "foo" attribute of items being filtered)

Link copied to clipboard

Creates an expression for getting the size (or length) of an attribute

Functions

Link copied to clipboard
abstract fun and(conditions: List<BooleanExpr>): BooleanExpr
open fun and(vararg conditions: BooleanExpr): BooleanExpr

Creates a boolean expression for verifying that multiple conditions are all met

Link copied to clipboard
abstract infix fun AttributePath.contains(expr: Expression): BooleanExpr
open infix fun AttributePath.contains(value: Any?): BooleanExpr

Creates a contains expression for verifying this expression contains the given expression

Link copied to clipboard
abstract infix fun Expression.eq(expr: Expression): BooleanExpr
open infix fun Expression.eq(value: Boolean?): BooleanExpr
open infix fun Expression.eq(value: ByteArray?): BooleanExpr
open infix fun Expression.eq(value: Nothing?): BooleanExpr
open infix fun Expression.eq(value: Number?): BooleanExpr
open infix fun Expression.eq(value: String?): BooleanExpr
open infix fun Expression.eq(value: UByte?): BooleanExpr
open infix fun Expression.eq(value: UInt?): BooleanExpr
open infix fun Expression.eq(value: ULong?): BooleanExpr
open infix fun Expression.eq(value: UShort?): BooleanExpr
open infix fun Expression.eq(value: List<Any?>?): BooleanExpr
open infix fun Expression.eq(value: Map<String, Any?>?): BooleanExpr
@JvmName(name = "eqSetNumber")
open infix fun <N : Number> Expression.eq(value: Set<N>?): BooleanExpr
@JvmName(name = "eqSetByteArray")
open infix fun Expression.eq(value: Set<ByteArray>?): BooleanExpr
@JvmName(name = "eqSetString")
open infix fun Expression.eq(value: Set<String>?): BooleanExpr
@JvmName(name = "eqSetUByte")
open infix fun Expression.eq(value: Set<UByte>?): BooleanExpr
@JvmName(name = "eqSetUInt")
open infix fun Expression.eq(value: Set<UInt>?): BooleanExpr
@JvmName(name = "eqSetULong")
open infix fun Expression.eq(value: Set<ULong>?): BooleanExpr
@JvmName(name = "eqSetUShort")
open infix fun Expression.eq(value: Set<UShort>?): BooleanExpr

Creates an equality expression for verifying two expressions are equal to each other

Link copied to clipboard

Creates an expression for verifying an attribute exists

Link copied to clipboard
abstract infix fun Expression.gt(expr: Expression): BooleanExpr
open infix fun Expression.gt(value: ByteArray): BooleanExpr
open infix fun Expression.gt(value: Number): BooleanExpr
open infix fun Expression.gt(value: String): BooleanExpr
open infix fun Expression.gt(value: UByte): BooleanExpr
open infix fun Expression.gt(value: UInt): BooleanExpr
open infix fun Expression.gt(value: ULong): BooleanExpr
open infix fun Expression.gt(value: UShort): BooleanExpr

Creates an inequality expression for verifying this expression is greater than another expression

Link copied to clipboard
abstract infix fun Expression.gte(expr: Expression): BooleanExpr
open infix fun Expression.gte(value: ByteArray): BooleanExpr
open infix fun Expression.gte(value: Number): BooleanExpr
open infix fun Expression.gte(value: String): BooleanExpr
open infix fun Expression.gte(value: UByte): BooleanExpr
open infix fun Expression.gte(value: UInt): BooleanExpr
open infix fun Expression.gte(value: ULong): BooleanExpr
open infix fun Expression.gte(value: UShort): BooleanExpr

Creates an inequality expression for verifying this expression is greater than or equal to another expression

Link copied to clipboard

Creates a range expression for verifying this expression is between two other expressions

Link copied to clipboard
@JvmName(name = "isInCollectionNumber")
open infix fun <N : Number> AttributePath.isIn(set: Collection<N?>): BooleanExpr
@JvmName(name = "isInCollectionExpression")
abstract infix fun AttributePath.isIn(set: Collection<Expression>): BooleanExpr
@JvmName(name = "isInCollectionByteArray")
open infix fun AttributePath.isIn(set: Collection<ByteArray?>): BooleanExpr
@JvmName(name = "isInCollectionString")
open infix fun AttributePath.isIn(set: Collection<String?>): BooleanExpr
@JvmName(name = "isInCollectionUByte")
open infix fun AttributePath.isIn(set: Collection<UByte?>): BooleanExpr
@JvmName(name = "isInCollectionUInt")
open infix fun AttributePath.isIn(set: Collection<UInt?>): BooleanExpr
@JvmName(name = "isInCollectionULong")
open infix fun AttributePath.isIn(set: Collection<ULong?>): BooleanExpr
@JvmName(name = "isInCollectionUShort")
open infix fun AttributePath.isIn(set: Collection<UShort?>): BooleanExpr
@JvmName(name = "isInCollectionList")
open infix fun AttributePath.isIn(set: Collection<List<Any?>?>): BooleanExpr
@JvmName(name = "isInCollectionMap")
open infix fun AttributePath.isIn(set: Collection<Map<String, Any?>?>): BooleanExpr
@JvmName(name = "isInCollectionSetNumber")
open infix fun <N : Number> AttributePath.isIn(set: Collection<Set<N>?>): BooleanExpr
@JvmName(name = "isInCollectionSetByteArray")
open infix fun AttributePath.isIn(set: Collection<Set<ByteArray>?>): BooleanExpr
@JvmName(name = "isInCollectionSetString")
open infix fun AttributePath.isIn(set: Collection<Set<String>?>): BooleanExpr
@JvmName(name = "isInCollectionSetUByte")
open infix fun AttributePath.isIn(set: Collection<Set<UByte>?>): BooleanExpr
@JvmName(name = "isInCollectionSetUInt")
open infix fun AttributePath.isIn(set: Collection<Set<UInt>?>): BooleanExpr
@JvmName(name = "isInCollectionSetULong")
open infix fun AttributePath.isIn(set: Collection<Set<ULong>?>): BooleanExpr
@JvmName(name = "isInCollectionSetUShort")
open infix fun AttributePath.isIn(set: Collection<Set<UShort>?>): BooleanExpr

Creates a contains expression for verifying this expression is in the given set of elements

@JvmName(name = "isInRangeNumber")
open infix fun <N : Number, Comparable<N>> AttributePath.isIn(range: ClosedRange<N>): BooleanExpr
@JvmName(name = "isInRangeString")
open infix fun AttributePath.isIn(range: ClosedRange<String>): BooleanExpr
@JvmName(name = "isInRangeUByte")
open infix fun AttributePath.isIn(range: ClosedRange<UByte>): BooleanExpr
@JvmName(name = "isInRangeUInt")
open infix fun AttributePath.isIn(range: ClosedRange<UInt>): BooleanExpr
@JvmName(name = "isInRangeULong")
open infix fun AttributePath.isIn(range: ClosedRange<ULong>): BooleanExpr
@JvmName(name = "isInRangeUShort")
open infix fun AttributePath.isIn(range: ClosedRange<UShort>): BooleanExpr

Creates a range expression for verifying this expression is in the given range

Link copied to clipboard
abstract infix fun AttributePath.isOfType(type: AttributeType): BooleanExpr

Creates an expression for verifying an attribute exists

Link copied to clipboard
abstract infix fun Expression.lt(expr: Expression): BooleanExpr
open infix fun Expression.lt(value: ByteArray): BooleanExpr
open infix fun Expression.lt(value: Number): BooleanExpr
open infix fun Expression.lt(value: String): BooleanExpr
open infix fun Expression.lt(value: UByte): BooleanExpr
open infix fun Expression.lt(value: UInt): BooleanExpr
open infix fun Expression.lt(value: ULong): BooleanExpr
open infix fun Expression.lt(value: UShort): BooleanExpr

Creates an inequality expression for verifying this expression is less than another expression

Link copied to clipboard
abstract infix fun Expression.lte(expr: Expression): BooleanExpr
open infix fun Expression.lte(value: ByteArray): BooleanExpr
open infix fun Expression.lte(value: Number): BooleanExpr
open infix fun Expression.lte(value: String): BooleanExpr
open infix fun Expression.lte(value: UByte): BooleanExpr
open infix fun Expression.lte(value: UInt): BooleanExpr
open infix fun Expression.lte(value: ULong): BooleanExpr
open infix fun Expression.lte(value: UShort): BooleanExpr

Creates an inequality expression for verifying this expression is less than or equal to another expression

Link copied to clipboard
abstract infix fun Expression.neq(expr: Expression): BooleanExpr
open infix fun Expression.neq(value: Boolean?): BooleanExpr
open infix fun Expression.neq(value: ByteArray?): BooleanExpr
open infix fun Expression.neq(value: Nothing?): BooleanExpr
open infix fun Expression.neq(value: Number?): BooleanExpr
open infix fun Expression.neq(value: String?): BooleanExpr
open infix fun Expression.neq(value: UByte?): BooleanExpr
open infix fun Expression.neq(value: UInt?): BooleanExpr
open infix fun Expression.neq(value: ULong?): BooleanExpr
open infix fun Expression.neq(value: UShort?): BooleanExpr
open infix fun Expression.neq(value: List<Any?>?): BooleanExpr
open infix fun Expression.neq(value: Map<String, Any?>?): BooleanExpr
@JvmName(name = "neqSetNumber")
open infix fun <N : Number> Expression.neq(value: Set<N>?): BooleanExpr
@JvmName(name = "neqSetByteArray")
open infix fun Expression.neq(value: Set<ByteArray>?): BooleanExpr
@JvmName(name = "neqSetString")
open infix fun Expression.neq(value: Set<String>?): BooleanExpr
@JvmName(name = "neqSetUByte")
open infix fun Expression.neq(value: Set<UByte>?): BooleanExpr
@JvmName(name = "neqSetUInt")
open infix fun Expression.neq(value: Set<UInt>?): BooleanExpr
@JvmName(name = "neqSetULong")
open infix fun Expression.neq(value: Set<ULong>?): BooleanExpr
@JvmName(name = "neqSetUShort")
open infix fun Expression.neq(value: Set<UShort>?): BooleanExpr

Creates an inequality expression for verifying two expressions are not equal to each other

Link copied to clipboard
abstract fun not(condition: BooleanExpr): BooleanExpr

Creates a boolean expression for verifying the opposite of a condition is met

Link copied to clipboard

Creates an expression for verifying an attribute does not exist

Link copied to clipboard
abstract fun or(conditions: List<BooleanExpr>): BooleanExpr
open fun or(vararg conditions: BooleanExpr): BooleanExpr

Creates a boolean expression for verifying that at least one of several conditions is met

Link copied to clipboard
abstract infix fun AttributePath.startsWith(expr: Expression): BooleanExpr
open infix fun AttributePath.startsWith(value: String): BooleanExpr

Creates an expression for verifying this attribute starts with the given expression