Skip to content

Commit a3301b9

Browse files
committed
add index hint support for distinct command
1 parent 6bb4005 commit a3301b9

File tree

17 files changed

+327
-9
lines changed

17 files changed

+327
-9
lines changed

driver-core/src/main/com/mongodb/internal/operation/AsyncOperations.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,9 @@ public <TResult> AsyncReadOperation<AsyncBatchCursor<TResult>> find(final MongoN
181181
}
182182

183183
public <TResult> AsyncReadOperation<AsyncBatchCursor<TResult>> distinct(final String fieldName, final Bson filter,
184-
final Class<TResult> resultClass, final Collation collation, final BsonValue comment) {
185-
return operations.distinct(fieldName, filter, resultClass, collation, comment);
184+
final Class<TResult> resultClass, final Collation collation, final BsonValue comment, final Bson hint,
185+
final String hintString) {
186+
return operations.distinct(fieldName, filter, resultClass, collation, comment, hint, hintString);
186187
}
187188

188189
public <TResult> AsyncExplainableReadOperation<AsyncBatchCursor<TResult>> aggregate(

driver-core/src/main/com/mongodb/internal/operation/DistinctOperation.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ public class DistinctOperation<T> implements AsyncReadOperation<AsyncBatchCursor
5454
private BsonDocument filter;
5555
private Collation collation;
5656
private BsonValue comment;
57+
private BsonValue hint;
58+
private String hintString;
5759

5860
public DistinctOperation(final MongoNamespace namespace, final String fieldName, final Decoder<T> decoder) {
5961
this.namespace = notNull("namespace", namespace);
@@ -97,6 +99,24 @@ public DistinctOperation<T> comment(final BsonValue comment) {
9799
return this;
98100
}
99101

102+
public BsonValue getHint() {
103+
return hint;
104+
}
105+
106+
public DistinctOperation<T> hint(@Nullable final BsonValue hint) {
107+
this.hint = hint;
108+
return this;
109+
}
110+
111+
public String getHintString() {
112+
return hintString;
113+
}
114+
115+
public DistinctOperation<T> hintString(@Nullable final String hint) {
116+
this.hintString = hint;
117+
return this;
118+
}
119+
100120
@Override
101121
public BatchCursor<T> execute(final ReadBinding binding) {
102122
return executeRetryableRead(binding, namespace.getDatabaseName(), getCommandCreator(), createCommandDecoder(),
@@ -124,6 +144,7 @@ private CommandCreator getCommandCreator() {
124144
commandDocument.put("collation", collation.asDocument());
125145
}
126146
putIfNotNull(commandDocument, "comment", comment);
147+
putIfNotNull(commandDocument, "hint", hint);
127148
return commandDocument;
128149
};
129150
}

driver-core/src/main/com/mongodb/internal/operation/Operations.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,13 +217,14 @@ private <TResult> FindOperation<TResult> createFindOperation(final MongoNamespac
217217
}
218218

219219
<TResult> DistinctOperation<TResult> distinct(final String fieldName, @Nullable final Bson filter, final Class<TResult> resultClass,
220-
final Collation collation, final BsonValue comment) {
220+
final Collation collation, final BsonValue comment, @Nullable final Bson hint, @Nullable final String hintString) {
221221
return new DistinctOperation<>(assertNotNull(namespace),
222222
fieldName, codecRegistry.get(resultClass))
223223
.retryReads(retryReads)
224224
.filter(filter == null ? null : filter.toBsonDocument(documentClass, codecRegistry))
225225
.collation(collation)
226-
.comment(comment);
226+
.comment(comment)
227+
.hint(hint != null ? toBsonDocument(hint) : (hintString != null ? new BsonString(hintString) : null));
227228
}
228229

229230
<TResult> AggregateOperation<TResult> aggregate(final List<? extends Bson> pipeline, final Class<TResult> resultClass,

driver-core/src/main/com/mongodb/internal/operation/SyncOperations.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,9 @@ public <TResult> ReadOperation<BatchCursor<TResult>> find(final MongoNamespace f
165165

166166
public <TResult> ReadOperation<BatchCursor<TResult>> distinct(final String fieldName, final Bson filter,
167167
final Class<TResult> resultClass,
168-
final Collation collation, final BsonValue comment) {
169-
return operations.distinct(fieldName, filter, resultClass, collation, comment);
168+
final Collation collation, final BsonValue comment,
169+
final Bson hint, final String hintString) {
170+
return operations.distinct(fieldName, filter, resultClass, collation, comment, hint, hintString);
170171
}
171172

172173
public <TResult> ExplainableReadOperation<BatchCursor<TResult>> aggregate(final List<? extends Bson> pipeline,
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
{
2+
"description": "distinct-hint",
3+
"schemaVersion": "1.0",
4+
"runOnRequirements": [
5+
{
6+
"minServerVersion": "7.1.0"
7+
}
8+
],
9+
"createEntities": [
10+
{
11+
"client": {
12+
"id": "client0",
13+
"observeEvents": [
14+
"commandStartedEvent"
15+
]
16+
}
17+
},
18+
{
19+
"database": {
20+
"id": "database0",
21+
"client": "client0",
22+
"databaseName": "distinct-hint-tests"
23+
}
24+
},
25+
{
26+
"collection": {
27+
"id": "collection0",
28+
"database": "database0",
29+
"collectionName": "coll0"
30+
}
31+
}
32+
],
33+
"initialData": [
34+
{
35+
"collectionName": "coll0",
36+
"databaseName": "distinct-hint-tests",
37+
"documents": [
38+
{
39+
"_id": 1,
40+
"x": 11
41+
},
42+
{
43+
"_id": 2,
44+
"x": 22
45+
},
46+
{
47+
"_id": 3,
48+
"x": 33
49+
}
50+
]
51+
}
52+
],
53+
"tests": [
54+
{
55+
"description": "distinct with hint string",
56+
"operations": [
57+
{
58+
"name": "distinct",
59+
"object": "collection0",
60+
"arguments": {
61+
"fieldName": "x",
62+
"filter": {
63+
"_id": 1
64+
},
65+
"hint": "_id_"
66+
},
67+
"expectResult": [
68+
11
69+
]
70+
}
71+
],
72+
"expectEvents": [
73+
{
74+
"client": "client0",
75+
"events": [
76+
{
77+
"commandStartedEvent": {
78+
"command": {
79+
"distinct": "coll0",
80+
"key": "x",
81+
"query": {
82+
"_id": 1
83+
},
84+
"hint": "_id_"
85+
},
86+
"commandName": "distinct",
87+
"databaseName": "distinct-hint-tests"
88+
}
89+
}
90+
]
91+
}
92+
]
93+
},
94+
{
95+
"description": "distinct with hint document",
96+
"operations": [
97+
{
98+
"name": "distinct",
99+
"object": "collection0",
100+
"arguments": {
101+
"fieldName": "x",
102+
"filter": {
103+
"_id": 1
104+
},
105+
"hint": {
106+
"_id": 1
107+
}
108+
},
109+
"expectResult": [
110+
11
111+
]
112+
}
113+
],
114+
"expectEvents": [
115+
{
116+
"client": "client0",
117+
"events": [
118+
{
119+
"commandStartedEvent": {
120+
"command": {
121+
"distinct": "coll0",
122+
"key": "x",
123+
"query": {
124+
"_id": 1
125+
},
126+
"hint": {
127+
"_id": 1
128+
}
129+
},
130+
"commandName": "distinct",
131+
"databaseName": "distinct-hint-tests"
132+
}
133+
}
134+
]
135+
}
136+
]
137+
}
138+
]
139+
}

driver-kotlin-coroutine/src/integration/kotlin/com/mongodb/kotlin/client/coroutine/syncadapter/SyncDistinctIterable.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ data class SyncDistinctIterable<T : Any>(val wrapped: DistinctFlow<T>) :
3333
override fun collation(collation: Collation?): SyncDistinctIterable<T> = apply { wrapped.collation(collation) }
3434
override fun comment(comment: String?): SyncDistinctIterable<T> = apply { wrapped.comment(comment) }
3535
override fun comment(comment: BsonValue?): SyncDistinctIterable<T> = apply { wrapped.comment(comment) }
36+
override fun hint(hint: Bson?): SyncDistinctIterable<T> = apply { wrapped.hint(hint) }
37+
override fun hintString(hint: String?): SyncDistinctIterable<T> = apply { wrapped.hintString(hint) }
3638
override fun timeoutMode(timeoutMode: TimeoutMode): SyncDistinctIterable<T> = apply {
3739
wrapped.timeoutMode(timeoutMode)
3840
}

driver-kotlin-coroutine/src/main/kotlin/com/mongodb/kotlin/client/coroutine/DistinctFlow.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import com.mongodb.annotations.Alpha
1919
import com.mongodb.annotations.Reason
2020
import com.mongodb.client.cursor.TimeoutMode
2121
import com.mongodb.client.model.Collation
22+
import com.mongodb.lang.Nullable
2223
import com.mongodb.reactivestreams.client.DistinctPublisher
2324
import java.util.concurrent.TimeUnit
2425
import kotlinx.coroutines.flow.Flow
@@ -103,5 +104,21 @@ public class DistinctFlow<T : Any>(private val wrapped: DistinctPublisher<T>) :
103104
*/
104105
public fun comment(comment: BsonValue?): DistinctFlow<T> = apply { wrapped.comment(comment) }
105106

107+
/**
108+
* Sets the hint for which index to use. A null value means no hint is set.
109+
*
110+
* @param hint the hint
111+
* @return this
112+
*/
113+
public fun hint(@Nullable hint: Bson?): DistinctFlow<T> = apply { wrapped.hint(hint) }
114+
115+
/**
116+
* Sets the hint for which index to use. A null value means no hint is set.
117+
*
118+
* @param hint the name of the index which should be used for the operation
119+
* @return this
120+
*/
121+
public fun hintString(@Nullable hint: String?): DistinctFlow<T> = apply { wrapped.hintString(hint) }
122+
106123
public override suspend fun collect(collector: FlowCollector<T>): Unit = wrapped.asFlow().collect(collector)
107124
}

driver-kotlin-sync/src/integration/kotlin/com/mongodb/kotlin/client/syncadapter/SyncDistinctIterable.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,6 @@ internal class SyncDistinctIterable<T : Any>(val wrapped: DistinctIterable<T>) :
3636
override fun collation(collation: Collation?): SyncDistinctIterable<T> = apply { wrapped.collation(collation) }
3737
override fun comment(comment: String?): SyncDistinctIterable<T> = apply { wrapped.comment(comment) }
3838
override fun comment(comment: BsonValue?): SyncDistinctIterable<T> = apply { wrapped.comment(comment) }
39+
override fun hint(hint: Bson?): SyncDistinctIterable<T> = apply { wrapped.hint(hint) }
40+
override fun hintString(hint: String?): SyncDistinctIterable<T> = apply { wrapped.hintString(hint) }
3941
}

driver-kotlin-sync/src/main/kotlin/com/mongodb/kotlin/client/DistinctIterable.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import com.mongodb.annotations.Reason
2020
import com.mongodb.client.DistinctIterable as JDistinctIterable
2121
import com.mongodb.client.cursor.TimeoutMode
2222
import com.mongodb.client.model.Collation
23+
import com.mongodb.lang.Nullable
2324
import java.util.concurrent.TimeUnit
2425
import org.bson.BsonValue
2526
import org.bson.conversions.Bson
@@ -99,4 +100,20 @@ public class DistinctIterable<T : Any?>(private val wrapped: JDistinctIterable<T
99100
* @return this
100101
*/
101102
public fun comment(comment: BsonValue?): DistinctIterable<T> = apply { wrapped.comment(comment) }
103+
104+
/**
105+
* Sets the hint for which index to use. A null value means no hint is set.
106+
*
107+
* @param hint the hint
108+
* @return this
109+
*/
110+
public fun hint(@Nullable hint: Bson?): DistinctIterable<T> = apply { wrapped.hint(hint) }
111+
112+
/**
113+
* Sets the hint for which index to use. A null value means no hint is set.
114+
*
115+
* @param hint the name of the index which should be used for the operation
116+
* @return this
117+
*/
118+
public fun hintString(@Nullable hint: String?): DistinctIterable<T> = apply { wrapped.hintString(hint) }
102119
}

driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/DistinctPublisher.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,24 @@ public interface DistinctPublisher<TResult> extends Publisher<TResult> {
9797
*/
9898
DistinctPublisher<TResult> comment(@Nullable BsonValue comment);
9999

100+
/**
101+
* Sets the hint for which index to use. A null value means no hint is set.
102+
*
103+
* @param hint the hint
104+
* @return this
105+
* @since 5.3
106+
*/
107+
DistinctPublisher<TResult> hint(@Nullable Bson hint);
108+
109+
/**
110+
* Sets the hint for which index to use. A null value means no hint is set.
111+
*
112+
* @param hint the name of the index which should be used for the operation
113+
* @return this
114+
* @since 5.3
115+
*/
116+
DistinctPublisher<TResult> hintString(@Nullable String hint);
117+
100118
/**
101119
* Sets the timeoutMode for the cursor.
102120
*

driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/DistinctPublisherImpl.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ final class DistinctPublisherImpl<T> extends BatchCursorPublisher<T> implements
4141
private long maxTimeMS;
4242
private Collation collation;
4343
private BsonValue comment;
44+
private Bson hint;
45+
private String hintString;
4446

4547
DistinctPublisherImpl(
4648
@Nullable final ClientSession clientSession,
@@ -88,6 +90,18 @@ public DistinctPublisher<T> comment(@Nullable final BsonValue comment) {
8890
return this;
8991
}
9092

93+
@Override
94+
public DistinctPublisher<T> hint(@Nullable final Bson hint) {
95+
this.hint = hint;
96+
return this;
97+
}
98+
99+
@Override
100+
public DistinctPublisher<T> hintString(@Nullable final String hint) {
101+
this.hintString = hint;
102+
return this;
103+
}
104+
91105
@Override
92106
public DistinctPublisher<T> timeoutMode(final TimeoutMode timeoutMode) {
93107
super.timeoutMode(timeoutMode);
@@ -97,7 +111,7 @@ public DistinctPublisher<T> timeoutMode(final TimeoutMode timeoutMode) {
97111
@Override
98112
AsyncReadOperation<AsyncBatchCursor<T>> asAsyncReadOperation(final int initialBatchSize) {
99113
// initialBatchSize is ignored for distinct operations.
100-
return getOperations().distinct(fieldName, filter, getDocumentClass(), collation, comment);
114+
return getOperations().distinct(fieldName, filter, getDocumentClass(), collation, comment, hint, hintString);
101115
}
102116

103117
@Override

driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/syncadapter/SyncDistinctIterable.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,18 @@ public DistinctIterable<T> comment(@Nullable final BsonValue comment) {
7171
return this;
7272
}
7373

74+
@Override
75+
public DistinctIterable<T> hint(@Nullable final Bson hint) {
76+
wrapped.hint(hint);
77+
return this;
78+
}
79+
80+
@Override
81+
public DistinctIterable<T> hintString(final String hint) {
82+
wrapped.hintString(hint);
83+
return this;
84+
}
85+
7486
@Override
7587
public DistinctIterable<T> timeoutMode(final TimeoutMode timeoutMode) {
7688
wrapped.timeoutMode(timeoutMode);

driver-scala/src/integration/scala/org/mongodb/scala/syncadapter/SyncDistinctIterable.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,15 @@ case class SyncDistinctIterable[T](wrapped: DistinctObservable[T])
6161
wrapped.comment(comment)
6262
this
6363
}
64+
65+
override def hint(hint: Bson): DistinctIterable[T] = {
66+
wrapped.hint(hint)
67+
this
68+
}
69+
70+
override def hintString(hint: String): DistinctIterable[T] = {
71+
wrapped.hintString(hint)
72+
this
73+
}
74+
6475
}

0 commit comments

Comments
 (0)