Skip to content

Commit 27ee659

Browse files
authored
GODRIVER-3412 Add index hint support for distinct command. (#1888)
1 parent a74791f commit 27ee659

File tree

6 files changed

+257
-0
lines changed

6 files changed

+257
-0
lines changed

internal/integration/unified/collection_operation_execution.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,8 @@ func executeDistinct(ctx context.Context, operation *operation) (*operationResul
523523
val := elem.Value()
524524

525525
switch key {
526+
case "hint":
527+
opts.SetHint(val)
526528
case "collation":
527529
collation, err := createCollation(val.Document())
528530
if err != nil {

mongo/collection.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,6 +1281,16 @@ func (coll *Collection) Distinct(
12811281
}
12821282
op.Comment(comment)
12831283
}
1284+
if args.Hint != nil {
1285+
if isUnorderedMap(args.Hint) {
1286+
return &DistinctResult{err: ErrMapForOrderedArgument{"hint"}}
1287+
}
1288+
hint, err := marshalValue(args.Hint, coll.bsonOpts, coll.registry)
1289+
if err != nil {
1290+
return &DistinctResult{err: err}
1291+
}
1292+
op.Hint(hint)
1293+
}
12841294
retry := driver.RetryNone
12851295
if coll.client.retryReads {
12861296
retry = driver.RetryOncePerCommand

mongo/options/distinctoptions.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ package options
1313
type DistinctOptions struct {
1414
Collation *Collation
1515
Comment interface{}
16+
Hint interface{}
1617
}
1718

1819
// DistinctOptionsBuilder contains options to configure distinct operations. Each
@@ -60,3 +61,21 @@ func (do *DistinctOptionsBuilder) SetComment(comment interface{}) *DistinctOptio
6061

6162
return do
6263
}
64+
65+
// SetHint specifies the index to use for the operation. This should either be
66+
// the index name as a string or the index specification as a document. This
67+
// option is only valid for MongoDB versions >= 7.1. Previous server versions
68+
// will return an error if an index hint is specified. Distinct returns an error
69+
// if the hint parameter is a multi-key map. The default value is nil, which
70+
// means that no index hint will be sent.
71+
//
72+
// SetHint sets the Hint field.
73+
func (do *DistinctOptionsBuilder) SetHint(hint interface{}) *DistinctOptionsBuilder {
74+
do.Opts = append(do.Opts, func(opts *DistinctOptions) error {
75+
opts.Hint = hint
76+
77+
return nil
78+
})
79+
80+
return do
81+
}
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+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
description: "distinct-hint"
2+
3+
schemaVersion: "1.0"
4+
runOnRequirements:
5+
# https://jira.mongodb.org/browse/SERVER-14227
6+
# Server supports distinct with hint starting from 7.1.0.
7+
- minServerVersion: "7.1.0"
8+
9+
createEntities:
10+
- client:
11+
id: &client0 client0
12+
observeEvents: [ commandStartedEvent ]
13+
- database:
14+
id: &database0 database0
15+
client: *client0
16+
databaseName: &database0Name distinct-hint-tests
17+
- collection:
18+
id: &collection0 collection0
19+
database: *database0
20+
collectionName: &collection0Name coll0
21+
22+
initialData:
23+
- collectionName: *collection0Name
24+
databaseName: *database0Name
25+
documents:
26+
- { _id: 1, x: 11 }
27+
- { _id: 2, x: 22 }
28+
- { _id: 3, x: 33 }
29+
30+
tests:
31+
- description: "distinct with hint string"
32+
operations:
33+
- name: distinct
34+
object: *collection0
35+
arguments:
36+
fieldName: &fieldName x
37+
filter: &filter { _id: 1 }
38+
hint: _id_
39+
expectResult: [ 11 ]
40+
expectEvents:
41+
- client: *client0
42+
events:
43+
- commandStartedEvent:
44+
command:
45+
distinct: *collection0Name
46+
key: *fieldName
47+
query: *filter
48+
hint: _id_
49+
commandName: distinct
50+
databaseName: *database0Name
51+
52+
- description: "distinct with hint document"
53+
operations:
54+
- name: distinct
55+
object: *collection0
56+
arguments:
57+
fieldName: *fieldName
58+
filter: *filter
59+
hint:
60+
_id: 1
61+
expectResult: [ 11 ]
62+
expectEvents:
63+
- client: *client0
64+
events:
65+
- commandStartedEvent:
66+
command:
67+
distinct: *collection0Name
68+
key: *fieldName
69+
query: *filter
70+
hint:
71+
_id: 1
72+
commandName: distinct
73+
databaseName: *database0Name

x/mongo/driver/operation/distinct.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type Distinct struct {
3131
clock *session.ClusterClock
3232
collection string
3333
comment bsoncore.Value
34+
hint bsoncore.Value
3435
monitor *event.CommandMonitor
3536
crypt driver.Crypt
3637
database string
@@ -120,6 +121,9 @@ func (d *Distinct) command(dst []byte, desc description.SelectedServer) ([]byte,
120121
if d.comment.Type != bsoncore.Type(0) {
121122
dst = bsoncore.AppendValueElement(dst, "comment", d.comment)
122123
}
124+
if d.hint.Type != bsoncore.Type(0) {
125+
dst = bsoncore.AppendValueElement(dst, "hint", d.hint)
126+
}
123127
if d.key != nil {
124128
dst = bsoncore.AppendStringElement(dst, "key", *d.key)
125129
}
@@ -199,6 +203,16 @@ func (d *Distinct) Comment(comment bsoncore.Value) *Distinct {
199203
return d
200204
}
201205

206+
// Hint sets a value to help trace an operation.
207+
func (d *Distinct) Hint(hint bsoncore.Value) *Distinct {
208+
if d == nil {
209+
d = new(Distinct)
210+
}
211+
212+
d.hint = hint
213+
return d
214+
}
215+
202216
// CommandMonitor sets the monitor to use for APM events.
203217
func (d *Distinct) CommandMonitor(monitor *event.CommandMonitor) *Distinct {
204218
if d == nil {

0 commit comments

Comments
 (0)