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

Commit

Permalink
feat(dsl): $rename
Browse files Browse the repository at this point in the history
  • Loading branch information
CLOVIS-AI committed Jul 18, 2024
1 parent 60d18fa commit 116d10a
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 0 deletions.
1 change: 1 addition & 0 deletions dsl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
### Update

- [`$inc`][fr.qsh.ktmongo.dsl.expr.UpdateExpression.inc]
- [`$rename`][fr.qsh.ktmongo.dsl.expr.UpdateExpression.renameTo]
- [`$set`][fr.qsh.ktmongo.dsl.expr.UpdateExpression.set]
- [`$setOnInsert`][fr.qsh.ktmongo.dsl.expr.UpdateExpression.setOnInsert]
- [`$unset`][fr.qsh.ktmongo.dsl.expr.UpdateExpression.unset]
51 changes: 51 additions & 0 deletions dsl/src/main/kotlin/expr/UpdateExpression.kt
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,54 @@ class UpdateExpression<T>(
}
}

// endregion
// region $rename

/**
* Renames a field.
*
* ### Example
*
* ```kotlin
* class User(
* val name: String,
* val age: Int,
* val ageOld: Int,
* )
*
* collection.updateMany {
* User::ageOld renameTo User::age
* }
* ```
*
* ### External resources
*
* - [Official documentation](https://www.mongodb.com/docs/manual/reference/operator/update/rename/)
*/
@OptIn(LowLevelApi::class)
@KtMongoDsl
infix fun <@OnlyInputTypes V> KProperty1<T, V>.renameTo(newName: KProperty1<T, V>) {
accept(RenameExpressionNode(listOf(this.path() to newName.path()), codec))
}

@LowLevelApi
private class RenameExpressionNode(
val fields: List<Pair<Path, Path>>,
codec: CodecRegistry,
) : UpdateExpressionNode(codec) {
override fun simplify(): Expression? =
this.takeUnless { fields.isEmpty() }

override fun write(writer: BsonWriter) {
writer.writeDocument("\$rename") {
for ((before, after) in fields) {
writer.writeName(before.toString())
writer.writeString(after.toString())
}
}
}
}

// endregion

companion object {
Expand All @@ -293,6 +341,9 @@ class UpdateExpression<T>(
OperatorCombinator(UnsetExpressionNode::class) { sources, codec ->
UnsetExpressionNode(sources.flatMap { it.fields }, codec)
},
OperatorCombinator(RenameExpressionNode::class) { sources, codec ->
RenameExpressionNode(sources.flatMap { it.fields }, codec)
},
)
}
}
30 changes: 30 additions & 0 deletions dsl/src/test/kotlin/expr/UpdateExpressionTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package fr.qsh.ktmongo.dsl.expr
import fr.qsh.ktmongo.dsl.LowLevelApi
import fr.qsh.ktmongo.dsl.expr.common.withLoggedContext
import fr.qsh.ktmongo.dsl.path.div
import fr.qsh.ktmongo.dsl.path.get
import fr.qsh.ktmongo.dsl.writeDocument
import io.kotest.core.spec.style.FunSpec
import org.bson.BsonDocument
Expand Down Expand Up @@ -45,6 +46,7 @@ class UpdateExpressionTest : FunSpec({
val setOnInsert = "\$setOnInsert"
val inc = "\$inc"
val unset = "\$unset"
val rename = "\$rename"

test("Empty update") {
update<User> { } shouldBeBson """{}"""
Expand Down Expand Up @@ -209,4 +211,32 @@ class UpdateExpressionTest : FunSpec({
""".trimIndent()
}
}

context("Operator $rename") {
test("Single and nested field") {
update {
User::bestFriend / Friend::name renameTo User::name
} shouldBeBson """
{
"$rename": {
"bestFriend.name": "name"
}
}
""".trimIndent()
}

test("Multiple fields") {
update {
User::bestFriend / Friend::name renameTo User::name
User::friends[0] / Friend::name renameTo User::friends[1] / Friend::name
} shouldBeBson """
{
"$rename": {
"bestFriend.name": "name",
"friends.$0.name": "friends.$1.name"
}
}
""".trimIndent()
}
}
})

0 comments on commit 116d10a

Please sign in to comment.