Skip to content
This repository has been archived by the owner on Oct 2, 2024. It is now read-only.

Commit

Permalink
tmp
Browse files Browse the repository at this point in the history
  • Loading branch information
CLOVIS-AI committed Jul 19, 2024
1 parent c060055 commit 419ccfc
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 8 deletions.
10 changes: 10 additions & 0 deletions demo/src/main/kotlin/Main.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package fr.qsh.ktmongo.demo

import com.mongodb.kotlin.client.MongoClient
import fr.qsh.ktmongo.dsl.path.div
import fr.qsh.ktmongo.sync.asKtMongo
import fr.qsh.ktmongo.sync.filter

data class Jedi(
val name: String,
val age: Int,
val level: Int,
val friends: List<Friend>,
)

data class Friend(
val name: String,
)

fun main() {
Expand All @@ -30,4 +36,8 @@ fun main() {
Jedi::age set 19
Jedi::level inc 1
}

collection.find {
Jedi::friends.items() / Friend::name eq "Foo"
}
}
76 changes: 76 additions & 0 deletions dsl/src/main/kotlin/expr/FilterExpression.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import fr.qsh.ktmongo.dsl.KtMongoDsl
import fr.qsh.ktmongo.dsl.LowLevelApi
import fr.qsh.ktmongo.dsl.expr.common.CompoundExpression
import fr.qsh.ktmongo.dsl.expr.common.Expression
import fr.qsh.ktmongo.dsl.path.PropertyPath
import fr.qsh.ktmongo.dsl.path.path
import fr.qsh.ktmongo.dsl.writeArray
import fr.qsh.ktmongo.dsl.writeDocument
Expand Down Expand Up @@ -280,6 +281,9 @@ class FilterExpression<T>(
* ### External resources
*
* - [Official documentation](https://www.mongodb.com/docs/manual/reference/operator/query/eq/)
*
* @see eqNotNull To only filter when the value is non-null.
* @see contains To make an equality check on one of the elements of a collection.
*/
@KtMongoDsl
infix fun <@OnlyInputTypes V> KProperty1<T, V>.eq(value: V) {
Expand Down Expand Up @@ -351,6 +355,78 @@ class FilterExpression<T>(
this { ne(value) }
}

// endregion
// region Predicates on array elements

/**
* Allows to declare filters on the items of the specified field.
*
* ### Example
*
* This example will return all users who have at least one grade above 10:
* ```kotlin
* class User(
* val name: String,
* val grades: List<Int>,
* )
*
* collection.find {
* User::grades.items() gte 10
* }
* ```
*
* ### Behavior with non-array fields
*
* TODO
*
* ### Using multiple criteria
*
* @see fr.qsh.ktmongo.dsl.path.get Refer to a specific item by its index.
*/
@OptIn(LowLevelApi::class)
fun <@OnlyInputTypes V> KProperty1<T, Collection<V>>.items(): KProperty1<T, V> =
PropertyPath(
path = this.path(),
backingProperty = this,
)

/**
* Matches documents where one of the items in the specified field is [value].
*
* ### Example
*
* ```kotlin
* class User(
* val name: String,
* val addresses: List<String>,
* )
*
* collection.find {
* User::addresses contains "Some address"
* }
* ```
*
* All documents for which one of the `addresses` is equal to "Some address" are returned.
*
* ### Behavior with non-array fields
*
* MongoDB doesn't make a difference between "checking if one of the elements of an array matches the predicate" and "checking if the field matches the predicate".
*
* In the previous example, if a document had a field named `addresses` that was a `String` (**not** a `List<String>`), and its value was "Some address", it would be returned as well.
*
* ### External resources
*
* - [Official documentation](https://www.mongodb.com/docs/manual/reference/operator/query/eq/#array-element-equals-a-value)
*
* @see eq To make an equality check on the array itself, instead of one its elements.
* @see items Perform other kinds of filters on one of the items of an array.
* @see UpdateExpression.matched Update the element item matched by this function.
*/
@KtMongoDsl
infix fun <@OnlyInputTypes V> KProperty1<T, Collection<V>>.contains(value: V) {
this.items() eq value
}

// endregion
// region $exists

Expand Down
7 changes: 7 additions & 0 deletions dsl/src/main/kotlin/expr/PredicateExpression.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ import org.bson.codecs.configuration.CodecRegistry
* DSL for MongoDB operators that are used as predicates in conditions in a context where the targeted field is already
* specified.
*/
// TODO: PredicateExpression should allow further property nesting
// {
// "foo": {
// "$gte": 10,
// "bar": 11
// }
// }
@KtMongoDsl
class PredicateExpression<T>(
codec: CodecRegistry,
Expand Down
37 changes: 35 additions & 2 deletions dsl/src/main/kotlin/expr/UpdateExpression.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import fr.qsh.ktmongo.dsl.LowLevelApi
import fr.qsh.ktmongo.dsl.expr.common.CompoundExpression
import fr.qsh.ktmongo.dsl.expr.common.Expression
import fr.qsh.ktmongo.dsl.expr.common.acceptAll
import fr.qsh.ktmongo.dsl.path.Path
import fr.qsh.ktmongo.dsl.path.path
import fr.qsh.ktmongo.dsl.path.*
import fr.qsh.ktmongo.dsl.writeDocument
import fr.qsh.ktmongo.dsl.writeObject
import org.bson.BsonWriter
Expand Down Expand Up @@ -324,6 +323,40 @@ class UpdateExpression<T>(
}
}

// endregion
// region Array indexing operators: $, $[]

/**
* Selects the item matched by [contains][FilterExpression.contains].
*
* ### Example
*
* ```kotlin
* class User(
* val name: String,
* val friends: List<Friend>,
* )
*
* class Friend(
* val name: String,
* val score: Int,
* )
*
* collection.filter {
* User::name eq "Foo"
* User::friends contains {
* Friend:: TODO
* }
* }
* ```
*/
@OptIn(LowLevelApi::class)
fun <T0, T1> KProperty1<T0, Collection<T1>>.matched(): KProperty1<T0, T1> =
PropertyPath(
path = this.path() + PathSegment.Positional,
backingProperty = this,
)

// endregion

companion object {
Expand Down
2 changes: 1 addition & 1 deletion dsl/src/main/kotlin/path/PropertyPath.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import kotlin.reflect.*
*/
@LowLevelApi
@Suppress("NO_REFLECTION_IN_CLASS_PATH") // None of the functions are called by our code. The caller is responsible for fixing this.
private class PropertyPath<RootParent, Value>(
internal class PropertyPath<RootParent, Value>(
/**
* The path of this property.
*
Expand Down
44 changes: 39 additions & 5 deletions dsl/src/test/kotlin/expr/FilterExpressionTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ class FilterExpressionTest : FunSpec({
val type = "\$type"
val not = "\$not"
val isOneOf = "\$in"
val gt = "\$gt"
val gte = "\$gte"
val lt = "\$lt"
val lte = "\$lte"

context("Operator $eq") {
test("Integer") {
Expand Down Expand Up @@ -376,11 +380,6 @@ class FilterExpressionTest : FunSpec({
}

context("Comparison operators") {
val gt = "\$gt"
val gte = "\$gte"
val lt = "\$lt"
val lte = "\$lte"

test("int $gt") {
filter {
User::age gt 12
Expand Down Expand Up @@ -429,4 +428,39 @@ class FilterExpressionTest : FunSpec({
""".trimIndent()
}
}

context("Array operators") {
class Grades(
val userId: String,
val grades: List<Int>,
)

test("Search for a specific grade") {
filter {
Grades::grades contains 12
} shouldBeBson """
{
"grades": {
"$eq": 12
}
}
""".trimIndent()
}

test("Search for a set of grades") {
filter {
Grades::grades contains {
gt(10)
lte(12)
}
} shouldBeBson """
{
"grades": {
"$gt": 10,
"$lte": 12
}
}
""".trimIndent()
}
}
})

0 comments on commit 419ccfc

Please sign in to comment.