Skip to content

Commit e53349b

Browse files
committed
Adding extensions for Aggregators and Accumulators (#1562)
* Adding extensions for Aggregators and Accumulators
1 parent e573a17 commit e53349b

File tree

8 files changed

+1152
-2
lines changed

8 files changed

+1152
-2
lines changed

driver-core/src/main/com/mongodb/ServerAddress.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public ServerAddress(@Nullable final String host, final int port) {
103103
if (hostToUse.startsWith("[")) {
104104
int idx = host.indexOf("]");
105105
if (idx == -1) {
106-
throw new IllegalArgumentException("an IPV6 address must be encosed with '[' and ']'"
106+
throw new IllegalArgumentException("an IPV6 address must be enclosed with '[' and ']'"
107107
+ " according to RFC 2732.");
108108
}
109109

driver-core/src/main/com/mongodb/client/model/UnwindOptions.java

+22
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import com.mongodb.lang.Nullable;
2020

21+
import java.util.Objects;
22+
2123
/**
2224
* The options for an unwind aggregation pipeline stage
2325
*
@@ -79,4 +81,24 @@ public String toString() {
7981
+ ", includeArrayIndex='" + includeArrayIndex + '\''
8082
+ '}';
8183
}
84+
85+
@Override
86+
public boolean equals(final Object o) {
87+
if (this == o) {
88+
return true;
89+
}
90+
if (o == null || getClass() != o.getClass()) {
91+
return false;
92+
}
93+
94+
UnwindOptions that = (UnwindOptions) o;
95+
return Objects.equals(preserveNullAndEmptyArrays, that.preserveNullAndEmptyArrays) && Objects.equals(includeArrayIndex, that.includeArrayIndex);
96+
}
97+
98+
@Override
99+
public int hashCode() {
100+
int result = Objects.hashCode(preserveNullAndEmptyArrays);
101+
result = 31 * result + Objects.hashCode(includeArrayIndex);
102+
return result;
103+
}
82104
}

driver-kotlin-extensions/build.gradle.kts

+8
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,25 @@ description = "The MongoDB Kotlin Driver Extensions"
3737

3838
ext.set("pomName", "MongoDB Kotlin Driver Extensions")
3939

40+
java { registerFeature("kotlinDrivers") { usingSourceSet(sourceSets["main"]) } }
41+
4042
dependencies {
4143
// Align versions of all Kotlin components
4244
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
4345
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
4446

4547
api(project(path = ":driver-core", configuration = "default"))
4648

49+
// Some extensions require higher API like MongoCollection which are defined in the sync &
50+
// coroutine Kotlin driver
51+
"kotlinDriversImplementation"(project(path = ":driver-kotlin-sync", configuration = "default"))
52+
"kotlinDriversImplementation"(project(path = ":driver-kotlin-coroutine", configuration = "default"))
53+
4754
testImplementation("org.jetbrains.kotlin:kotlin-reflect")
4855
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
4956
testImplementation("org.assertj:assertj-core:3.24.2")
5057
testImplementation("io.github.classgraph:classgraph:4.8.154")
58+
testImplementation("org.mockito.kotlin:mockito-kotlin:4.1.0")
5159
}
5260

5361
kotlin { explicitApi() }

driver-kotlin-extensions/src/main/kotlin/com/mongodb/kotlin/client/model/Accumulators.kt

+503
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
/*
2+
* Copyright 2008-present MongoDB, Inc.
3+
* Copyright (C) 2016/2022 Litote
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
* @custom-license-header
18+
*/
19+
package com.mongodb.kotlin.client.model
20+
21+
import com.mongodb.client.model.Aggregates
22+
import com.mongodb.client.model.GraphLookupOptions
23+
import com.mongodb.client.model.MergeOptions
24+
import com.mongodb.client.model.UnwindOptions
25+
import com.mongodb.client.model.densify.DensifyOptions
26+
import com.mongodb.client.model.densify.DensifyRange
27+
import com.mongodb.kotlin.client.model.Projections.projection
28+
import kotlin.reflect.KProperty
29+
import kotlin.reflect.KProperty1
30+
import org.bson.conversions.Bson
31+
32+
/**
33+
* Aggregates extension methods to improve Kotlin interop
34+
*
35+
* @since 5.3
36+
*/
37+
public object Aggregates {
38+
/**
39+
* Creates a $count pipeline stage using the named field to store the result
40+
*
41+
* @param property the data class field in which to store the count
42+
* @return the $count pipeline stage @mongodb.driver.manual reference/operator/aggregation/count/ $count
43+
*/
44+
public fun <T> count(property: KProperty<T>): Bson = Aggregates.count(property.path())
45+
46+
/**
47+
* Creates a $lookup pipeline stage, joining the current collection with the one specified in from using the given
48+
* pipeline. If the first stage in the pipeline is a {@link Aggregates#documents(List) $documents} stage, then the
49+
* {@code from} collection is ignored.
50+
*
51+
* @param from the collection in the same database to perform the join with.
52+
* @param localField the data class field from the local collection to match values against.
53+
* @param foreignField the data class field in the from collection to match values against.
54+
* @param pipeline the pipeline to run on the joined collection.
55+
* @param as the name of the new array field to add to the input documents.
56+
* @return the $lookup pipeline stage @mongodb.driver.manual reference/operator/aggregation/lookup/
57+
* $lookup @mongodb.server.release 3.6
58+
*/
59+
public fun <FROM : Any> lookup(
60+
from: com.mongodb.kotlin.client.MongoCollection<FROM>,
61+
localField: KProperty1<out Any, Any?>,
62+
foreignField: KProperty1<FROM, Any?>,
63+
newAs: String
64+
): Bson = Aggregates.lookup(from.namespace.collectionName, localField.path(), foreignField.path(), newAs)
65+
66+
/**
67+
* Creates a $lookup pipeline stage, joining the current collection with the one specified in from using the given
68+
* pipeline. If the first stage in the pipeline is a {@link Aggregates#documents(List) $documents} stage, then the
69+
* {@code from} collection is ignored.
70+
*
71+
* @param from the collection in the same database to perform the join with.
72+
* @param localField the data class field from the local collection to match values against.
73+
* @param foreignField the data class field in the from collection to match values against.
74+
* @param pipeline the pipeline to run on the joined collection.
75+
* @param as the name of the new array field to add to the input documents.
76+
* @return the $lookup pipeline stage @mongodb.driver.manual reference/operator/aggregation/lookup/
77+
* $lookup @mongodb.server.release 3.6
78+
*/
79+
public fun <FROM : Any> lookup(
80+
from: com.mongodb.kotlin.client.coroutine.MongoCollection<FROM>,
81+
localField: KProperty1<out Any, Any?>,
82+
foreignField: KProperty1<FROM, Any?>,
83+
newAs: String
84+
): Bson = Aggregates.lookup(from.namespace.collectionName, localField.path(), foreignField.path(), newAs)
85+
86+
/**
87+
* Creates a graphLookup pipeline stage for the specified filter
88+
*
89+
* @param <TExpression> the expression type
90+
* @param from the collection to query
91+
* @param startWith the expression to start the graph lookup with
92+
* @param connectFromField the data class from field
93+
* @param connectToField the data class to field
94+
* @param fieldAs name of field in output document
95+
* @param options optional values for the graphLookup
96+
* @return the $graphLookup pipeline stage @mongodb.driver.manual reference/operator/aggregation/graphLookup/
97+
* $graphLookup @mongodb.server.release 3.4
98+
*/
99+
@Suppress("LongParameterList")
100+
public fun <TExpression, FROM : Any> graphLookup(
101+
from: com.mongodb.kotlin.client.MongoCollection<FROM>,
102+
startWith: TExpression,
103+
connectFromField: KProperty1<FROM, Any?>,
104+
connectToField: KProperty1<FROM, Any?>,
105+
fieldAs: String,
106+
options: GraphLookupOptions = GraphLookupOptions()
107+
): Bson =
108+
Aggregates.graphLookup(
109+
from.namespace.collectionName, startWith, connectFromField.path(), connectToField.path(), fieldAs, options)
110+
111+
/**
112+
* Creates a graphLookup pipeline stage for the specified filter
113+
*
114+
* @param <TExpression> the expression type
115+
* @param from the collection to query
116+
* @param startWith the expression to start the graph lookup with
117+
* @param connectFromField the data class from field
118+
* @param connectToField the data class to field
119+
* @param fieldAs name of field in output document
120+
* @param options optional values for the graphLookup
121+
* @return the $graphLookup pipeline stage @mongodb.driver.manual reference/operator/aggregation/graphLookup/
122+
* $graphLookup @mongodb.server.release 3.4
123+
*/
124+
@Suppress("LongParameterList")
125+
public fun <TExpression, FROM : Any> graphLookup(
126+
from: com.mongodb.kotlin.client.coroutine.MongoCollection<FROM>,
127+
startWith: TExpression,
128+
connectFromField: KProperty1<FROM, Any?>,
129+
connectToField: KProperty1<FROM, Any?>,
130+
fieldAs: String,
131+
options: GraphLookupOptions = GraphLookupOptions()
132+
): Bson =
133+
Aggregates.graphLookup(
134+
from.namespace.collectionName, startWith, connectFromField.path(), connectToField.path(), fieldAs, options)
135+
136+
/**
137+
* Creates a $unionWith pipeline stage.
138+
*
139+
* @param collection the collection in the same database to perform the union with.
140+
* @param pipeline the pipeline to run on the union.
141+
* @return the $unionWith pipeline stage @mongodb.driver.manual reference/operator/aggregation/unionWith/
142+
* $unionWith @mongodb.server.release 4.4
143+
*/
144+
public fun unionWith(collection: com.mongodb.kotlin.client.MongoCollection<*>, pipeline: List<Bson>): Bson =
145+
Aggregates.unionWith(collection.namespace.collectionName, pipeline)
146+
147+
/**
148+
* Creates a $unionWith pipeline stage.
149+
*
150+
* @param collection the collection in the same database to perform the union with.
151+
* @param pipeline the pipeline to run on the union.
152+
* @return the $unionWith pipeline stage @mongodb.driver.manual reference/operator/aggregation/unionWith/
153+
* $unionWith @mongodb.server.release 4.4
154+
*/
155+
public fun unionWith(
156+
collection: com.mongodb.kotlin.client.coroutine.MongoCollection<*>,
157+
pipeline: List<Bson>
158+
): Bson = Aggregates.unionWith(collection.namespace.collectionName, pipeline)
159+
160+
/**
161+
* Creates a $unwind pipeline stage for the specified field name, which must be prefixed by a {@code '$'} sign.
162+
*
163+
* @param property the data class field name
164+
* @param unwindOptions options for the unwind pipeline stage
165+
* @return the $unwind pipeline stage @mongodb.driver.manual reference/operator/aggregation/unwind/ $unwind
166+
*/
167+
public fun <T> unwind(property: KProperty<Iterable<T>?>, unwindOptions: UnwindOptions = UnwindOptions()): Bson {
168+
return if (unwindOptions == UnwindOptions()) {
169+
Aggregates.unwind(property.projection)
170+
} else {
171+
Aggregates.unwind(property.projection, unwindOptions)
172+
}
173+
}
174+
175+
/**
176+
* Creates a $out pipeline stage that writes into the specified collection
177+
*
178+
* @param collection the collection
179+
* @return the $out pipeline stage @mongodb.driver.manual reference/operator/aggregation/out/ $out
180+
*/
181+
public fun out(collection: com.mongodb.kotlin.client.MongoCollection<*>): Bson =
182+
Aggregates.out(collection.namespace.collectionName)
183+
184+
/**
185+
* Creates a $out pipeline stage that writes into the specified collection
186+
*
187+
* @param collection the collection
188+
* @return the $out pipeline stage @mongodb.driver.manual reference/operator/aggregation/out/ $out
189+
*/
190+
public fun out(collection: com.mongodb.kotlin.client.coroutine.MongoCollection<*>): Bson =
191+
Aggregates.out(collection.namespace.collectionName)
192+
193+
/**
194+
* Creates a $merge pipeline stage that merges into the specified collection
195+
*
196+
* @param collection the collection to merge into
197+
* @param options the merge options
198+
* @return the $merge pipeline stage @mongodb.driver.manual reference/operator/aggregation/merge/
199+
* $merge @mongodb.server.release 4.2
200+
*/
201+
public fun merge(
202+
collection: com.mongodb.kotlin.client.MongoCollection<*>,
203+
options: MergeOptions = MergeOptions()
204+
): Bson = Aggregates.merge(collection.namespace.collectionName, options)
205+
206+
/**
207+
* Creates a $merge pipeline stage that merges into the specified collection
208+
*
209+
* @param collection the collection to merge into
210+
* @param options the merge options
211+
* @return the $merge pipeline stage @mongodb.driver.manual reference/operator/aggregation/merge/
212+
* $merge @mongodb.server.release 4.2
213+
*/
214+
public fun merge(
215+
collection: com.mongodb.kotlin.client.coroutine.MongoCollection<*>,
216+
options: MergeOptions = MergeOptions()
217+
): Bson = Aggregates.merge(collection.namespace.collectionName, options)
218+
219+
/**
220+
* Creates a `$densify` pipeline stage, which adds documents to a sequence of documents where certain values in the
221+
* `field` are missing.
222+
*
223+
* @param field The field to densify.
224+
* @param range The range.
225+
* @return The requested pipeline stage. @mongodb.driver.manual reference/operator/aggregation/densify/
226+
* $densify @mongodb.driver.manual core/document/#dot-notation Dot notation @mongodb.server.release 5.1
227+
*/
228+
public fun <T> densify(property: KProperty<T>, range: DensifyRange): Bson =
229+
Aggregates.densify(property.path(), range)
230+
231+
/**
232+
* Creates a {@code $densify} pipeline stage, which adds documents to a sequence of documents where certain values
233+
* in the {@code field} are missing.
234+
*
235+
* @param field The field to densify.
236+
* @param range The range.
237+
* @param options The densify options. Specifying {@link DensifyOptions#densifyOptions()} is equivalent to calling
238+
* {@link #densify(String, DensifyRange)}.
239+
* @return The requested pipeline stage. @mongodb.driver.manual reference/operator/aggregation/densify/
240+
* $densify @mongodb.driver.manual core/document/#dot-notation Dot notation @mongodb.server.release 5.1
241+
*/
242+
public fun <T> densify(property: KProperty<T>, range: DensifyRange, options: DensifyOptions): Bson =
243+
Aggregates.densify(property.path(), range, options)
244+
}

0 commit comments

Comments
 (0)