diff --git a/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt b/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt index 745a3013..01a3b099 100644 --- a/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt +++ b/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt @@ -91,7 +91,8 @@ import opensavvy.ktmongo.dsl.path.Field * - [`$gte`][gte] * - [`$lte`][lte] * - * Combine values: + * Arithmetic operators: + * - [`$abs`][abs] * - [`$add`][plus] * * @see Value Representation of an aggregation value. diff --git a/dsl/src/commonMain/kotlin/aggregation/operators/ArithmeticValueOperators.kt b/dsl/src/commonMain/kotlin/aggregation/operators/ArithmeticValueOperators.kt index fe60cbbf..8ea1da8d 100644 --- a/dsl/src/commonMain/kotlin/aggregation/operators/ArithmeticValueOperators.kt +++ b/dsl/src/commonMain/kotlin/aggregation/operators/ArithmeticValueOperators.kt @@ -31,6 +31,56 @@ import opensavvy.ktmongo.dsl.aggregation.ValueDsl */ interface ArithmeticValueOperators : ValueOperators { + // region $abs + + /** + * The absolute value of a number. + * + * If the value is `null` or `NaN`, it is returned unchanged. + * + * ### Example + * + * ```kotlin + * class Sensor( + * val name: String, + * val startTemp: Int, + * val endTemp: Int, + * val diffTemp: Int, + * ) + * + * collection.updateManyWithPipeline(filter = { Sensor::diffTemp.isNull() }) { + * set { + * Sensor::diffTemp set abs(of(Sensor::startTemp) - of(Sensor::endTemp)) + * } + * } + * ``` + * + * ### External resources + * + * - [Official documentation](https://www.mongodb.com/docs/manual/reference/operator/aggregation/abs/) + */ + @OptIn(LowLevelApi::class) + @Suppress("INVISIBLE_REFERENCE") + @KtMongoDsl + fun abs(value: Value): Value = + AbsoluteValueOperator(context, value) + + @OptIn(LowLevelApi::class) + private class AbsoluteValueOperator( + context: BsonContext, + private val value: Value + ) : AbstractValue(context) { + + override fun write(writer: BsonValueWriter) = with(writer) { + writeDocument { + write("\$abs") { + value.writeTo(this) + } + } + } + } + + // endregion // region $add /** diff --git a/dsl/src/commonTest/kotlin/aggregation/AggregationTestUtils.kt b/dsl/src/commonTest/kotlin/aggregation/AggregationTestUtils.kt index 1b5f7f07..b8c3fbc0 100644 --- a/dsl/src/commonTest/kotlin/aggregation/AggregationTestUtils.kt +++ b/dsl/src/commonTest/kotlin/aggregation/AggregationTestUtils.kt @@ -27,6 +27,7 @@ val match = "\$match" val sample = "\$sample" val skip = "\$skip" val set = "\$set" +val abs = "\$abs" val add = "\$add" @OptIn(LowLevelApi::class) diff --git a/dsl/src/commonTest/kotlin/aggregation/operators/ArithmeticValueOperatorsTest.kt b/dsl/src/commonTest/kotlin/aggregation/operators/ArithmeticValueOperatorsTest.kt index e3b42c69..cd9d0ed9 100644 --- a/dsl/src/commonTest/kotlin/aggregation/operators/ArithmeticValueOperatorsTest.kt +++ b/dsl/src/commonTest/kotlin/aggregation/operators/ArithmeticValueOperatorsTest.kt @@ -29,6 +29,28 @@ class ArithmeticValueOperatorsTest : PreparedSpec({ val score = "\$score" val average = "\$average" + suite(abs) { + test("Usage with a number") { + TestPipeline() + .set { + Target::average set abs(of(5.2)) + } + .shouldBeBson(""" + [ + { + "$set": { + "average": { + "$abs": { + "$literal": 5.2 + } + } + } + } + ] + """.trimIndent()) + } + } + suite(add) { test("Binary usage") { TestPipeline() -- 2.51.2 From 69adeb7caf5707be13fdeba4cef590fdd958c169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Tue, 11 Feb 2025 22:28:51 +0100 Subject: [PATCH 02/10] feat(dsl): Add the $acos aggregation operator --- .../commonMain/kotlin/aggregation/ValueDsl.kt | 11 +-- .../operators/TrigonometryValueOperators.kt | 87 +++++++++++++++++++ .../TrigonometryValueOperatorsTest.kt | 61 +++++++++++++ 3 files changed, 154 insertions(+), 5 deletions(-) create mode 100644 dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt create mode 100644 dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt diff --git a/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt b/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt index 01a3b099..e0342897 100644 --- a/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt +++ b/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt @@ -17,10 +17,7 @@ package opensavvy.ktmongo.dsl.aggregation import opensavvy.ktmongo.dsl.KtMongoDsl -import opensavvy.ktmongo.dsl.aggregation.operators.ArithmeticValueOperators -import opensavvy.ktmongo.dsl.aggregation.operators.ComparisonValueOperators -import opensavvy.ktmongo.dsl.aggregation.operators.ConditionalValueOperators -import opensavvy.ktmongo.dsl.aggregation.operators.ValueOperators +import opensavvy.ktmongo.dsl.aggregation.operators.* import opensavvy.ktmongo.dsl.expr.FilterOperators import opensavvy.ktmongo.dsl.path.Field @@ -95,10 +92,14 @@ import opensavvy.ktmongo.dsl.path.Field * - [`$abs`][abs] * - [`$add`][plus] * + * Trigonometric operators and angle management: + * - [`$acos`][acos] + * * @see Value Representation of an aggregation value. */ @KtMongoDsl interface ValueDsl : ValueOperators, ComparisonValueOperators, ConditionalValueOperators, - ArithmeticValueOperators + ArithmeticValueOperators, + TrigonometryValueOperators diff --git a/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt b/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt new file mode 100644 index 00000000..010f6571 --- /dev/null +++ b/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2025, OpenSavvy and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package opensavvy.ktmongo.dsl.aggregation.operators + +import opensavvy.ktmongo.bson.BsonContext +import opensavvy.ktmongo.bson.BsonValueWriter +import opensavvy.ktmongo.dsl.KtMongoDsl +import opensavvy.ktmongo.dsl.LowLevelApi +import opensavvy.ktmongo.dsl.aggregation.AbstractValue +import opensavvy.ktmongo.dsl.aggregation.Value +import opensavvy.ktmongo.dsl.aggregation.ValueDsl + +/** + * Operators to perform trigonometric and geometric operators. + * + * To learn more about aggregation operators, see [ValueDsl]. + */ +interface TrigonometryValueOperators : ValueOperators { + + // region $acos + + /** + * The inverse cosine (arc cosine) of a value, in radians. + * + * The value must be in the range `-1..1`. + * + * If the value is `null` or `NaN`, it is returned unchanged. + * + * ### Example + * + * ```kotlin + * class Triangle( + * val name: String, + * val sideA: Double, + * val sideB: Double, + * val hypotenuse: Double, + * val angleA: Double, + * ) + * + * collection.aggregate() + * .set { + * Triangle::angleA set acos(of(Triangle::sideB) / of(Triangle::hypotenuse)) + * } + * ``` + * + * ### External resources + * + * - [Official documentation](https://www.mongodb.com/docs/manual/reference/operator/aggregation/acos/) + */ + @OptIn(LowLevelApi::class) + @KtMongoDsl + fun acos(value: Value): Value = + UnaryTrigonometryOperator(context, "acos", value) + + // endregion + + @OptIn(LowLevelApi::class) + private class UnaryTrigonometryOperator( + context: BsonContext, + private val operatorName: String, + private val value: Value + ) : AbstractValue(context) { + + override fun write(writer: BsonValueWriter) = with(writer) { + writeDocument { + write("$$operatorName") { + value.writeTo(this) + } + } + } + } + +} diff --git a/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt b/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt new file mode 100644 index 00000000..3da81710 --- /dev/null +++ b/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2025, OpenSavvy and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package opensavvy.ktmongo.dsl.aggregation.operators + +import opensavvy.ktmongo.dsl.aggregation.TestPipeline +import opensavvy.ktmongo.dsl.aggregation.add +import opensavvy.ktmongo.dsl.aggregation.set +import opensavvy.ktmongo.dsl.aggregation.shouldBeBson +import opensavvy.prepared.runner.kotest.PreparedSpec + +val acos = "\$acos" + +class TrigonometryValueOperatorsTest : PreparedSpec({ + class Target( + val a: Double, + val b: Double, + val c: Double, + ) + + val a = "\$a" + val b = "\$b" + "\$c" + + test(acos) { + TestPipeline() + .set { + Target::c set acos(of(Target::a) + of(Target::b)) + } + .shouldBeBson(""" + [ + { + "$set": { + "c": { + "$acos": { + "$add": [ + "$a", + "$b" + ] + } + } + } + } + ] + """.trimIndent()) + } + +}) -- 2.51.2 From 64fdbd586bc4aed0d9a3709380bac07ab1dda624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Tue, 11 Feb 2025 22:42:50 +0100 Subject: [PATCH 03/10] refactor(dsl): Add default implementation to Field.div to facilitate usage --- dsl/src/commonMain/kotlin/path/Field.kt | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/dsl/src/commonMain/kotlin/path/Field.kt b/dsl/src/commonMain/kotlin/path/Field.kt index 32b9ff1f..48723772 100644 --- a/dsl/src/commonMain/kotlin/path/Field.kt +++ b/dsl/src/commonMain/kotlin/path/Field.kt @@ -105,8 +105,10 @@ interface Field<@Suppress("unused") Root, @Suppress("unused") out Type> { * * @see get Access a specific element of an array */ + @OptIn(LowLevelApi::class, DangerousMongoApi::class) @KtMongoDsl - operator fun div(child: Field): Field + operator fun div(child: Field): Field = + FieldImpl(path / child.path) /** * Refers to [child] as a nested field of the current field. @@ -135,8 +137,10 @@ interface Field<@Suppress("unused") Root, @Suppress("unused") out Type> { * * @see get Access a specific element of an array */ + @OptIn(LowLevelApi::class) @KtMongoDsl - operator fun div(child: KProperty1): Field + operator fun div(child: KProperty1): Field = + FieldImpl(path / PathSegment.Field(child.name)) } /** @@ -325,13 +329,6 @@ internal class FieldImpl( override val path: Path, ) : Field { - @OptIn(DangerousMongoApi::class) - override fun div(child: Field): Field = - FieldImpl(path / child.path) - - override fun div(child: KProperty1): Field = - FieldImpl(path / PathSegment.Field(child.name)) - override fun toString() = path.toString() // region Identity -- 2.51.2 From 1b4ec92a5b8276040f736fe0f9d09c8dce02bfec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Tue, 11 Feb 2025 23:43:07 +0100 Subject: [PATCH 04/10] feat(dsl): Add the $acosh aggregation operator --- .../commonMain/kotlin/aggregation/ValueDsl.kt | 1 + .../operators/TrigonometryValueOperators.kt | 33 ++++++++++++++++++- .../TrigonometryValueOperatorsTest.kt | 26 ++++++++++++--- 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt b/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt index e0342897..245e8b0c 100644 --- a/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt +++ b/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt @@ -94,6 +94,7 @@ import opensavvy.ktmongo.dsl.path.Field * * Trigonometric operators and angle management: * - [`$acos`][acos] + * - [`$acosh`][acosh] * * @see Value Representation of an aggregation value. */ diff --git a/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt b/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt index 010f6571..8ade35ea 100644 --- a/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt +++ b/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt @@ -31,7 +31,7 @@ import opensavvy.ktmongo.dsl.aggregation.ValueDsl */ interface TrigonometryValueOperators : ValueOperators { - // region $acos + // region cos/sin/tan /** * The inverse cosine (arc cosine) of a value, in radians. @@ -66,6 +66,37 @@ interface TrigonometryValueOperators : ValueOperators { fun acos(value: Value): Value = UnaryTrigonometryOperator(context, "acos", value) + /** + * The inverse hyperbolic cosine (hyperbolic arc cosine) of a value, in radians. + * + * The value must be in the range `1..∞`. + * + * If the value is `null` or `NaN`, it is returned unchanged. + * + * ### Example + * + * ```kotlin + * class Trigonometry( + * val name: String, + * val x: Double, + * val y: Double, + * ) + * + * collection.aggregate() + * .set { + * Trigonometry::y set acosh(of(Trigonometry::x)) + * } + * ``` + * + * ### External resources + * + * - [Official documentation](https://www.mongodb.com/docs/manual/reference/operator/aggregation/acosh/) + */ + @OptIn(LowLevelApi::class) + @KtMongoDsl + fun acosh(value: Value): Value = + UnaryTrigonometryOperator(context, "acosh", value) + // endregion @OptIn(LowLevelApi::class) diff --git a/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt b/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt index 3da81710..f9f6f39a 100644 --- a/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt +++ b/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt @@ -16,13 +16,11 @@ package opensavvy.ktmongo.dsl.aggregation.operators -import opensavvy.ktmongo.dsl.aggregation.TestPipeline -import opensavvy.ktmongo.dsl.aggregation.add -import opensavvy.ktmongo.dsl.aggregation.set -import opensavvy.ktmongo.dsl.aggregation.shouldBeBson +import opensavvy.ktmongo.dsl.aggregation.* import opensavvy.prepared.runner.kotest.PreparedSpec val acos = "\$acos" +val acosh = "\$acosh" class TrigonometryValueOperatorsTest : PreparedSpec({ class Target( @@ -58,4 +56,24 @@ class TrigonometryValueOperatorsTest : PreparedSpec({ """.trimIndent()) } + test(acosh) { + TestPipeline() + .set { + Target::c set acosh(of(2.0)) + } + .shouldBeBson(""" + [ + { + "$set": { + "c": { + "$acosh": { + "$literal": 2.0 + } + } + } + } + ] + """.trimIndent()) + } + }) -- 2.51.2 From 29594828a14474a772118ec4443dce11df8f177a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Tue, 11 Feb 2025 23:49:32 +0100 Subject: [PATCH 05/10] feat(dsl): Add the $asin & $asinh aggregation operators --- .../commonMain/kotlin/aggregation/ValueDsl.kt | 2 + .../operators/TrigonometryValueOperators.kt | 62 +++++++++++++++++++ .../TrigonometryValueOperatorsTest.kt | 40 +++++++++++- 3 files changed, 103 insertions(+), 1 deletion(-) diff --git a/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt b/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt index 245e8b0c..27a9ec39 100644 --- a/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt +++ b/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt @@ -95,6 +95,8 @@ import opensavvy.ktmongo.dsl.path.Field * Trigonometric operators and angle management: * - [`$acos`][acos] * - [`$acosh`][acosh] + * - [`$asin`][asin] + * - [`$asinh`][asinh] * * @see Value Representation of an aggregation value. */ diff --git a/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt b/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt index 8ade35ea..d7fc8305 100644 --- a/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt +++ b/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt @@ -97,6 +97,68 @@ interface TrigonometryValueOperators : ValueOperators { fun acosh(value: Value): Value = UnaryTrigonometryOperator(context, "acosh", value) + /** + * The inverse sine (arc sine) of a value, in radians. + * + * The value must be in the range `-1..1`. + * + * If the value is `null` or `NaN`, it is returned unchanged. + * + * ### Example + * + * ```kotlin + * class Triangle( + * val name: String, + * val sideA: Double, + * val sideB: Double, + * val hypotenuse: Double, + * val angleA: Double, + * ) + * + * collection.aggregate() + * .set { + * Triangle::angleA set asin(of(Triangle::sideA) / of(Triangle::hypotenuse)) + * } + * ``` + * + * ### External resources + * + * - [Official documentation](https://www.mongodb.com/docs/manual/reference/operator/aggregation/asin/) + */ + @OptIn(LowLevelApi::class) + @KtMongoDsl + fun asin(value: Value): Value = + UnaryTrigonometryOperator(context, "asin", value) + + /** + * The inverse hyperbolic sine (hyperbolic arc sine) of a value, in radians. + * + * If the value is `null` or `NaN`, it is returned unchanged. + * + * ### Example + * + * ```kotlin + * class Trigonometry( + * val name: String, + * val x: Double, + * val y: Double, + * ) + * + * collection.aggregate() + * .set { + * Trigonometry::y set asinh(of(Trigonometry::x)) + * } + * ``` + * + * ### External resources + * + * - [Official documentation](https://www.mongodb.com/docs/manual/reference/operator/aggregation/asinh/) + */ + @OptIn(LowLevelApi::class) + @KtMongoDsl + fun asinh(value: Value): Value = + UnaryTrigonometryOperator(context, "asinh", value) + // endregion @OptIn(LowLevelApi::class) diff --git a/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt b/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt index f9f6f39a..d0418ac7 100644 --- a/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt +++ b/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt @@ -21,6 +21,8 @@ import opensavvy.prepared.runner.kotest.PreparedSpec val acos = "\$acos" val acosh = "\$acosh" +val asin = "\$asin" +val asinh = "\$asinh" class TrigonometryValueOperatorsTest : PreparedSpec({ class Target( @@ -31,7 +33,7 @@ class TrigonometryValueOperatorsTest : PreparedSpec({ val a = "\$a" val b = "\$b" - "\$c" + val c = "\$c" test(acos) { TestPipeline() @@ -76,4 +78,40 @@ class TrigonometryValueOperatorsTest : PreparedSpec({ """.trimIndent()) } + test(asin) { + TestPipeline() + .set { + Target::b set asin(of(Target::c)) + } + .shouldBeBson(""" + [ + { + "$set": { + "b": { + "$asin": "$c" + } + } + } + ] + """.trimIndent()) + } + + test(asinh) { + TestPipeline() + .set { + Target::b set asinh(of(Target::c)) + } + .shouldBeBson(""" + [ + { + "$set": { + "b": { + "$asinh": "$c" + } + } + } + ] + """.trimIndent()) + } + }) -- 2.51.2 From 367f75d9c313d5d22ca9c6ae63024c129453bfde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Tue, 11 Feb 2025 23:55:48 +0100 Subject: [PATCH 06/10] feat(dsl): Add the $atan & $atanh aggregation operators --- .../commonMain/kotlin/aggregation/ValueDsl.kt | 2 + .../operators/TrigonometryValueOperators.kt | 62 +++++++++++++++++++ .../TrigonometryValueOperatorsTest.kt | 38 ++++++++++++ 3 files changed, 102 insertions(+) diff --git a/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt b/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt index 27a9ec39..8a9614bc 100644 --- a/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt +++ b/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt @@ -97,6 +97,8 @@ import opensavvy.ktmongo.dsl.path.Field * - [`$acosh`][acosh] * - [`$asin`][asin] * - [`$asinh`][asinh] + * - [`$atan`][atan] + * - [`$atanh`][atanh] * * @see Value Representation of an aggregation value. */ diff --git a/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt b/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt index d7fc8305..f0169e84 100644 --- a/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt +++ b/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt @@ -159,6 +159,68 @@ interface TrigonometryValueOperators : ValueOperators { fun asinh(value: Value): Value = UnaryTrigonometryOperator(context, "asinh", value) + /** + * The inverse tangent (arc tangent) of a value, in radians. + * + * If the value is `null` or `NaN`, it is returned unchanged. + * + * ### Example + * + * ```kotlin + * class Triangle( + * val name: String, + * val sideA: Double, + * val sideB: Double, + * val hypotenuse: Double, + * val angleA: Double, + * ) + * + * collection.aggregate() + * .set { + * Triangle::angleA set atan(of(Triangle::sideB) / of(Triangle::sideA)) + * } + * ``` + * + * ### External resources + * + * - [Official documentation](https://www.mongodb.com/docs/manual/reference/operator/aggregation/atan/) + */ + @OptIn(LowLevelApi::class) + @KtMongoDsl + fun atan(value: Value): Value = + UnaryTrigonometryOperator(context, "atan", value) + + /** + * The inverse hyperbolic tangent (hyperbolic arc tangent) of a value, in radians. + * + * The value must be in the range `-1..1`. + * + * If the value is `null` or `NaN`, it is returned unchanged. + * + * ### Example + * + * ```kotlin + * class Trigonometry( + * val name: String, + * val x: Double, + * val y: Double, + * ) + * + * collection.aggregate() + * .set { + * Trigonometry::y set atanh(of(Trigonometry::x)) + * } + * ``` + * + * ### External resources + * + * - [Official documentation](https://www.mongodb.com/docs/manual/reference/operator/aggregation/atanh/) + */ + @OptIn(LowLevelApi::class) + @KtMongoDsl + fun atanh(value: Value): Value = + UnaryTrigonometryOperator(context, "atanh", value) + // endregion @OptIn(LowLevelApi::class) diff --git a/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt b/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt index d0418ac7..a2347464 100644 --- a/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt +++ b/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt @@ -23,6 +23,8 @@ val acos = "\$acos" val acosh = "\$acosh" val asin = "\$asin" val asinh = "\$asinh" +val atan = "\$atan" +val atanh = "\$atanh" class TrigonometryValueOperatorsTest : PreparedSpec({ class Target( @@ -114,4 +116,40 @@ class TrigonometryValueOperatorsTest : PreparedSpec({ """.trimIndent()) } + test(atan) { + TestPipeline() + .set { + Target::b set atan(of(Target::c)) + } + .shouldBeBson(""" + [ + { + "$set": { + "b": { + "$atan": "$c" + } + } + } + ] + """.trimIndent()) + } + + test(atanh) { + TestPipeline() + .set { + Target::b set atanh(of(Target::c)) + } + .shouldBeBson(""" + [ + { + "$set": { + "b": { + "$atanh": "$c" + } + } + } + ] + """.trimIndent()) + } + }) -- 2.51.2 From a5d621eba57ceb86d5b392383e5424aeab5798ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 12 Feb 2025 14:21:51 +0100 Subject: [PATCH 07/10] feat(dsl): Add the $cos & $cosh aggregation operators --- .../commonMain/kotlin/aggregation/ValueDsl.kt | 2 + .../operators/TrigonometryValueOperators.kt | 60 +++++++++++++++++++ .../TrigonometryValueOperatorsTest.kt | 38 ++++++++++++ 3 files changed, 100 insertions(+) diff --git a/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt b/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt index 8a9614bc..47aa0082 100644 --- a/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt +++ b/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt @@ -99,6 +99,8 @@ import opensavvy.ktmongo.dsl.path.Field * - [`$asinh`][asinh] * - [`$atan`][atan] * - [`$atanh`][atanh] + * - [`$cos`][cos] + * - [`$cosh`][cosh] * * @see Value Representation of an aggregation value. */ diff --git a/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt b/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt index f0169e84..2396507e 100644 --- a/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt +++ b/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt @@ -97,6 +97,66 @@ interface TrigonometryValueOperators : ValueOperators { fun acosh(value: Value): Value = UnaryTrigonometryOperator(context, "acosh", value) + /** + * The cosine of a value that is measured in radians. + * + * If the value is `null` or `NaN`, it is returned unchanged. + * + * ### Example + * + * ```kotlin + * class Triangle( + * val name: String, + * val sideA: Double, + * val sideB: Double, + * val hypotenuse: Double, + * val angleA: Double, + * ) + * + * collection.aggregate() + * .set { + * Triangle::sideB set (of(cos(Triangle::angleA) * of(Triangle::hypotenuse))) + * } + * ``` + * + * ### External resources + * + * - [Official documentation](https://www.mongodb.com/docs/manual/reference/operator/aggregation/cos/) + */ + @OptIn(LowLevelApi::class) + @KtMongoDsl + fun cos(value: Value): Value = + UnaryTrigonometryOperator(context, "cos", value) + + /** + * The hyperbolic cosine of a value that is measured in radians. + * + * If the value is `null` or `NaN`, it is returned unchanged. + * + * ### Example + * + * ```kotlin + * class Trigonometry( + * val name: String, + * val angle: Double, + * val cosh: Double, + * ) + * + * collection.aggregate() + * .set { + * Trigonometry::cosh set cosh(of(Trigonometry::angle)) + * } + * ``` + * + * ### External resources + * + * - [Official documentation](https://www.mongodb.com/docs/manual/reference/operator/aggregation/cosh/) + */ + @OptIn(LowLevelApi::class) + @KtMongoDsl + fun cosh(value: Value): Value = + UnaryTrigonometryOperator(context, "cosh", value) + /** * The inverse sine (arc sine) of a value, in radians. * diff --git a/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt b/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt index a2347464..b6912659 100644 --- a/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt +++ b/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt @@ -19,6 +19,8 @@ package opensavvy.ktmongo.dsl.aggregation.operators import opensavvy.ktmongo.dsl.aggregation.* import opensavvy.prepared.runner.kotest.PreparedSpec +val cos = "\$cos" +val cosh = "\$cosh" val acos = "\$acos" val acosh = "\$acosh" val asin = "\$asin" @@ -37,6 +39,42 @@ class TrigonometryValueOperatorsTest : PreparedSpec({ val b = "\$b" val c = "\$c" + test(cos) { + TestPipeline() + .set { + Target::b set cos(of(Target::c)) + } + .shouldBeBson(""" + [ + { + "$set": { + "b": { + "$cos": "$c" + } + } + } + ] + """.trimIndent()) + } + + test(cosh) { + TestPipeline() + .set { + Target::b set cosh(of(Target::c)) + } + .shouldBeBson(""" + [ + { + "$set": { + "b": { + "$cosh": "$c" + } + } + } + ] + """.trimIndent()) + } + test(acos) { TestPipeline() .set { -- 2.51.2 From 5e98f9002c43c4209225fd3995040fb68be7bbb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 12 Feb 2025 14:31:18 +0100 Subject: [PATCH 08/10] feat(dsl): Add the $degreesToRadians & $radiansToDegrees aggregation operators --- .../commonMain/kotlin/aggregation/ValueDsl.kt | 2 + .../operators/TrigonometryValueOperators.kt | 61 +++++++++++++++++++ .../TrigonometryValueOperatorsTest.kt | 39 ++++++++++++ 3 files changed, 102 insertions(+) diff --git a/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt b/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt index 47aa0082..8ca44655 100644 --- a/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt +++ b/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt @@ -101,6 +101,8 @@ import opensavvy.ktmongo.dsl.path.Field * - [`$atanh`][atanh] * - [`$cos`][cos] * - [`$cosh`][cosh] + * - [`$degreesToRadians`][toRadians] + * - [`$radiansToDegrees`][toDegrees] * * @see Value Representation of an aggregation value. */ diff --git a/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt b/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt index 2396507e..a6017610 100644 --- a/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt +++ b/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt @@ -281,6 +281,67 @@ interface TrigonometryValueOperators : ValueOperators { fun atanh(value: Value): Value = UnaryTrigonometryOperator(context, "atanh", value) + // endregion + // region °/radians + + /** + * Converts an angle in degrees to an angle in radians. + * + * ### Example + * + * ```kotlin + * class Trigonometry( + * val angleADeg: Double, + * val angleARad: Double, + * ) + * + * collection.updateManyWithPipeline { + * set { + * Trigonometry::angleARad set of(Trigonometry::angleADeg).toRadians() + * } + * } + * ``` + * + * ### External resources + * + * - [Official documentation](https://www.mongodb.com/docs/manual/reference/operator/aggregation/degreesToRadians/) + * + * @see toDegrees Opposite operation + */ + @OptIn(LowLevelApi::class) + @KtMongoDsl + fun Value.toRadians(): Value = + UnaryTrigonometryOperator(context, "degreesToRadians", this) + + /** + * Converts an angle in radians to an angle in degrees. + * + * ### Example + * + * ```kotlin + * class Trigonometry( + * val angleADeg: Double, + * val angleARad: Double, + * ) + * + * collection.updateManyWithPipeline { + * set { + * Trigonometry::angleADeg set of(Trigonometry::angleARad).toDegrees() + * } + * } + * ``` + * + * ### External resources + * + * - [Official documentation](https://www.mongodb.com/docs/manual/reference/operator/aggregation/radiansToDegrees/) + * + * @see toRadians Opposite operation + */ + @OptIn(LowLevelApi::class) + @KtMongoDsl + fun Value.toDegrees(): Value = + UnaryTrigonometryOperator(context, "radiansToDegrees", this) + // endregion @OptIn(LowLevelApi::class) diff --git a/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt b/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt index b6912659..08eeb522 100644 --- a/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt +++ b/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt @@ -28,6 +28,9 @@ val asinh = "\$asinh" val atan = "\$atan" val atanh = "\$atanh" +val degreesToRadians = "\$degreesToRadians" +val radiansToDegrees = "\$radiansToDegrees" + class TrigonometryValueOperatorsTest : PreparedSpec({ class Target( val a: Double, @@ -190,4 +193,40 @@ class TrigonometryValueOperatorsTest : PreparedSpec({ """.trimIndent()) } + test(degreesToRadians) { + TestPipeline() + .set { + Target::b set of(Target::c).toRadians() + } + .shouldBeBson(""" + [ + { + "$set": { + "b": { + "$degreesToRadians": "$c" + } + } + } + ] + """.trimIndent()) + } + + test(radiansToDegrees) { + TestPipeline() + .set { + Target::b set of(Target::c).toDegrees() + } + .shouldBeBson(""" + [ + { + "$set": { + "b": { + "$radiansToDegrees": "$c" + } + } + } + ] + """.trimIndent()) + } + }) -- 2.51.2 From 0afb9a0c9b56bf01eeb3a5d33a17f84e532ca1ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 12 Feb 2025 14:40:38 +0100 Subject: [PATCH 09/10] feat(dsl): Add the $sin & $sinh aggregation operators --- .../commonMain/kotlin/aggregation/ValueDsl.kt | 2 + .../operators/TrigonometryValueOperators.kt | 60 +++++++++++++++++++ .../TrigonometryValueOperatorsTest.kt | 38 ++++++++++++ 3 files changed, 100 insertions(+) diff --git a/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt b/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt index 8ca44655..a04c7af0 100644 --- a/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt +++ b/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt @@ -101,6 +101,8 @@ import opensavvy.ktmongo.dsl.path.Field * - [`$atanh`][atanh] * - [`$cos`][cos] * - [`$cosh`][cosh] + * - [`$sin`][sin] + * - [`$sinh`][sinh] * - [`$degreesToRadians`][toRadians] * - [`$radiansToDegrees`][toDegrees] * diff --git a/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt b/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt index a6017610..0bd8434d 100644 --- a/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt +++ b/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt @@ -219,6 +219,66 @@ interface TrigonometryValueOperators : ValueOperators { fun asinh(value: Value): Value = UnaryTrigonometryOperator(context, "asinh", value) + /** + * The sine of a value that is measured in radians. + * + * If the value is `null` or `NaN`, it is returned unchanged. + * + * ### Example + * + * ```kotlin + * class Triangle( + * val name: String, + * val sideA: Double, + * val sideB: Double, + * val hypotenuse: Double, + * val angleA: Double, + * ) + * + * collection.aggregate() + * .set { + * Triangle::sideB set (sin(of(Trigonometry::angleA)) * of(Trigonometry::hypotenuse)) + * } + * ``` + * + * ### External resources + * + * - [Official documentation](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sin/) + */ + @OptIn(LowLevelApi::class) + @KtMongoDsl + fun sin(value: Value): Value = + UnaryTrigonometryOperator(context, "sin", value) + + /** + * The hyperbolic sine of a value that is measured in radians. + * + * If the value is `null` or `NaN`, it is returned unchanged. + * + * ### Example + * + * ```kotlin + * class Trigonometry( + * val name: String, + * val x: Double, + * val y: Double, + * ) + * + * collection.aggregate() + * .set { + * Trigonometry::y set sinh(of(Trigonometry::x)) + * } + * ``` + * + * ### External resources + * + * - [Official documentation](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sinh/) + */ + @OptIn(LowLevelApi::class) + @KtMongoDsl + fun sinh(value: Value): Value = + UnaryTrigonometryOperator(context, "sinh", value) + /** * The inverse tangent (arc tangent) of a value, in radians. * diff --git a/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt b/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt index 08eeb522..f6d6f985 100644 --- a/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt +++ b/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt @@ -23,6 +23,8 @@ val cos = "\$cos" val cosh = "\$cosh" val acos = "\$acos" val acosh = "\$acosh" +val sin = "\$sin" +val sinh = "\$sinh" val asin = "\$asin" val asinh = "\$asinh" val atan = "\$atan" @@ -121,6 +123,42 @@ class TrigonometryValueOperatorsTest : PreparedSpec({ """.trimIndent()) } + test(sin) { + TestPipeline() + .set { + Target::b set sin(of(Target::c)) + } + .shouldBeBson(""" + [ + { + "$set": { + "b": { + "$sin": "$c" + } + } + } + ] + """.trimIndent()) + } + + test(sinh) { + TestPipeline() + .set { + Target::b set sinh(of(Target::c)) + } + .shouldBeBson(""" + [ + { + "$set": { + "b": { + "$sinh": "$c" + } + } + } + ] + """.trimIndent()) + } + test(asin) { TestPipeline() .set { -- 2.51.2 From ed156b7b6bf1fcdd016fe7defd6375f45ea3b4a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 12 Feb 2025 14:49:31 +0100 Subject: [PATCH 10/10] feat(dsl): Add the $tan & $tanh aggregation operators --- .../commonMain/kotlin/aggregation/ValueDsl.kt | 2 + .../operators/TrigonometryValueOperators.kt | 60 +++++++++++++++++++ .../TrigonometryValueOperatorsTest.kt | 38 ++++++++++++ 3 files changed, 100 insertions(+) diff --git a/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt b/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt index a04c7af0..74c7802b 100644 --- a/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt +++ b/dsl/src/commonMain/kotlin/aggregation/ValueDsl.kt @@ -103,6 +103,8 @@ import opensavvy.ktmongo.dsl.path.Field * - [`$cosh`][cosh] * - [`$sin`][sin] * - [`$sinh`][sinh] + * - [`$tan`][tan] + * - [`$tanh`][tanh] * - [`$degreesToRadians`][toRadians] * - [`$radiansToDegrees`][toDegrees] * diff --git a/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt b/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt index 0bd8434d..6ed4d8a4 100644 --- a/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt +++ b/dsl/src/commonMain/kotlin/aggregation/operators/TrigonometryValueOperators.kt @@ -341,6 +341,66 @@ interface TrigonometryValueOperators : ValueOperators { fun atanh(value: Value): Value = UnaryTrigonometryOperator(context, "atanh", value) + /** + * The tangent of a value that is measured in radians. + * + * If the value is `null` or `NaN`, it is returned unchanged. + * + * ### Example + * + * ```kotlin + * class Triangle( + * val name: String, + * val sideA: Double, + * val sideB: Double, + * val hypotenuse: Double, + * val angleA: Double, + * ) + * + * collection.aggregate() + * .set { + * Triangle::sideB set (tan(of(Trigonometry::angleA) * of(Trigonometry::sideA))) + * } + * ``` + * + * ### External resources + * + * - [Official documentation](https://www.mongodb.com/docs/manual/reference/operator/aggregation/tan/) + */ + @OptIn(LowLevelApi::class) + @KtMongoDsl + fun tan(value: Value): Value = + UnaryTrigonometryOperator(context, "tan", value) + + /** + * The hyperbolic tangent of a value that is measured in radians. + * + * If the value is `null` or `NaN`, it is returned unchanged. + * + * ### Example + * + * ```kotlin + * class Trigonometry( + * val name: String, + * val x: Double, + * val y: Double, + * ) + * + * collection.aggregate() + * .set { + * Trigonometry::y set tanh(of(Trigonometry::x)) + * } + * ``` + * + * ### External resources + * + * - [Official documentation](https://www.mongodb.com/docs/manual/reference/operator/aggregation/tanh/) + */ + @OptIn(LowLevelApi::class) + @KtMongoDsl + fun tanh(value: Value): Value = + UnaryTrigonometryOperator(context, "tanh", value) + // endregion // region °/radians diff --git a/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt b/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt index f6d6f985..94e314b6 100644 --- a/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt +++ b/dsl/src/commonTest/kotlin/aggregation/operators/TrigonometryValueOperatorsTest.kt @@ -27,6 +27,8 @@ val sin = "\$sin" val sinh = "\$sinh" val asin = "\$asin" val asinh = "\$asinh" +val tan = "\$tan" +val tanh = "\$tanh" val atan = "\$atan" val atanh = "\$atanh" @@ -195,6 +197,42 @@ class TrigonometryValueOperatorsTest : PreparedSpec({ """.trimIndent()) } + test(tan) { + TestPipeline() + .set { + Target::b set tan(of(Target::c)) + } + .shouldBeBson(""" + [ + { + "$set": { + "b": { + "$tan": "$c" + } + } + } + ] + """.trimIndent()) + } + + test(tanh) { + TestPipeline() + .set { + Target::b set tanh(of(Target::c)) + } + .shouldBeBson(""" + [ + { + "$set": { + "b": { + "$tanh": "$c" + } + } + } + ] + """.trimIndent()) + } + test(atan) { TestPipeline() .set {