Skip to content

Commit 26d24ce

Browse files
committed
CSHARP-1978, CSHARP-2045: added hint and comment support to aggregate.
1 parent ae4c630 commit 26d24ce

File tree

11 files changed

+540
-3
lines changed

11 files changed

+540
-3
lines changed

src/MongoDB.Driver.Core/Core/Misc/Feature.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ public class Feature
2626
private static readonly Feature __aggregate = new Feature("Aggregate", new SemanticVersion(2, 2, 0));
2727
private static readonly Feature __aggregateAllowDiskUse = new Feature("AggregateAllowDiskUse", new SemanticVersion(2, 6, 0));
2828
private static readonly Feature __aggregateBucketStage = new Feature("AggregateBucketStage", new SemanticVersion(3, 3, 11));
29+
private static readonly Feature __aggregateComment = new Feature("AggregateComment", new SemanticVersion(3, 6, 0, "rc0"));
2930
private static readonly Feature __aggregateCountStage = new Feature("AggregateCountStage", new SemanticVersion(3, 3, 11));
3031
private static readonly Feature __aggregateCursorResult = new Feature("AggregateCursorResult", new SemanticVersion(2, 6, 0));
3132
private static readonly Feature __aggregateExplain = new Feature("AggregateExplain", new SemanticVersion(2, 6, 0));
3233
private static readonly Feature __aggregateFacetStage = new Feature("AggregateFacetStage", new SemanticVersion(3, 4, 0, "rc0"));
3334
private static readonly Feature __aggregateGraphLookupStage = new Feature("AggregateGraphLookupStage", new SemanticVersion(3, 4, 0, "rc0"));
35+
private static readonly Feature __aggregateHint = new Feature("AggregateHint", new SemanticVersion(3, 6, 0, "rc0"));
3436
private static readonly Feature __aggregateOut = new Feature("Aggregate", new SemanticVersion(2, 6, 0));
3537
private static readonly ArrayFiltersFeature __arrayFilters = new ArrayFiltersFeature("ArrayFilters", new SemanticVersion(3, 5, 11));
3638
private static readonly Feature __bypassDocumentValidation = new Feature("BypassDocumentValidation", new SemanticVersion(3, 2, 0));
@@ -72,6 +74,11 @@ public class Feature
7274
/// </summary>
7375
public static Feature AggregateBucketStage => __aggregateBucketStage;
7476

77+
/// <summary>
78+
/// Gets the aggregate comment feature.
79+
/// </summary>
80+
public static Feature AggregateComment => __aggregateComment;
81+
7582
/// <summary>
7683
/// Gets the aggregate count stage feature.
7784
/// </summary>
@@ -97,6 +104,11 @@ public class Feature
97104
/// </summary>
98105
public static Feature AggregateGraphLookupStage => __aggregateGraphLookupStage;
99106

107+
/// <summary>
108+
/// Gets the aggregate hint feature.
109+
/// </summary>
110+
public static Feature AggregateHint => __aggregateHint;
111+
100112
/// <summary>
101113
/// Gets the aggregate out feature.
102114
/// </summary>

src/MongoDB.Driver.Core/Core/Operations/AggregateExplainOperation.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ public class AggregateExplainOperation : IReadOperation<BsonDocument>
3535
private bool? _allowDiskUse;
3636
private Collation _collation;
3737
private CollectionNamespace _collectionNamespace;
38+
private string _comment;
39+
private BsonValue _hint;
3840
private TimeSpan? _maxTime;
3941
private MessageEncoderSettings _messageEncoderSettings;
4042
private IReadOnlyList<BsonDocument> _pipeline;
@@ -89,6 +91,30 @@ public CollectionNamespace CollectionNamespace
8991
get { return _collectionNamespace; }
9092
}
9193

94+
/// <summary>
95+
/// Gets or sets the comment.
96+
/// </summary>
97+
/// <value>
98+
/// The comment.
99+
/// </value>
100+
public string Comment
101+
{
102+
get { return _comment; }
103+
set { _comment = value; }
104+
}
105+
106+
/// <summary>
107+
/// Gets or sets the hint. This must either be a BsonString representing the index name or a BsonDocument representing the key pattern of the index.
108+
/// </summary>
109+
/// <value>
110+
/// The hint.
111+
/// </value>
112+
public BsonValue Hint
113+
{
114+
get { return _hint; }
115+
set { _hint = value; }
116+
}
117+
92118
/// <summary>
93119
/// Gets or sets the maximum time the server should spend on this operation.
94120
/// </summary>
@@ -135,7 +161,9 @@ internal BsonDocument CreateCommand(SemanticVersion serverVersion)
135161
{ "pipeline", new BsonArray(_pipeline) },
136162
{ "allowDiskUse", () => _allowDiskUse.Value, _allowDiskUse.HasValue },
137163
{ "maxTimeMS", () => _maxTime.Value.TotalMilliseconds, _maxTime.HasValue },
138-
{ "collation", () => _collation.ToBsonDocument(), _collation != null }
164+
{ "collation", () => _collation.ToBsonDocument(), _collation != null },
165+
{ "hint", () => _hint, _hint != null },
166+
{ "comment", () => _comment, _comment != null }
139167
};
140168
}
141169

src/MongoDB.Driver.Core/Core/Operations/AggregateOperation.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ public class AggregateOperation<TResult> : IReadOperation<IAsyncCursor<TResult>>
4141
private int? _batchSize;
4242
private Collation _collation;
4343
private readonly CollectionNamespace _collectionNamespace;
44+
private string _comment;
45+
private BsonValue _hint;
4446
private TimeSpan? _maxAwaitTime;
4547
private TimeSpan? _maxTime;
4648
private readonly MessageEncoderSettings _messageEncoderSettings;
@@ -110,6 +112,30 @@ public CollectionNamespace CollectionNamespace
110112
get { return _collectionNamespace; }
111113
}
112114

115+
/// <summary>
116+
/// Gets or sets the comment.
117+
/// </summary>
118+
/// <value>
119+
/// The comment.
120+
/// </value>
121+
public string Comment
122+
{
123+
get { return _comment; }
124+
set { _comment = value; }
125+
}
126+
127+
/// <summary>
128+
/// Gets or sets the hint. This must either be a BsonString representing the index name or a BsonDocument representing the key pattern of the index.
129+
/// </summary>
130+
/// <value>
131+
/// The hint.
132+
/// </value>
133+
public BsonValue Hint
134+
{
135+
get { return _hint; }
136+
set { _hint = value; }
137+
}
138+
113139
/// <summary>
114140
/// Gets or sets the maximum await time.
115141
/// </summary>
@@ -252,7 +278,9 @@ internal BsonDocument CreateCommand(ConnectionDescription connectionDescription,
252278
{ "pipeline", new BsonArray(_pipeline) },
253279
{ "allowDiskUse", () => _allowDiskUse.Value, _allowDiskUse.HasValue },
254280
{ "maxTimeMS", () => _maxTime.Value.TotalMilliseconds, _maxTime.HasValue },
255-
{ "collation", () => _collation.ToBsonDocument(), _collation != null }
281+
{ "collation", () => _collation.ToBsonDocument(), _collation != null },
282+
{ "hint", () => _hint, _hint != null },
283+
{ "comment", () => _comment, _comment != null }
256284
};
257285

258286
ReadConcernHelper.AppendReadConcern(command, _readConcern, connectionDescription, session);

src/MongoDB.Driver.Core/Core/Operations/AggregateToCollectionOperation.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ public class AggregateToCollectionOperation : IWriteOperation<BsonDocument>
3636
private bool? _bypassDocumentValidation;
3737
private Collation _collation;
3838
private readonly CollectionNamespace _collectionNamespace;
39+
private string _comment;
40+
private BsonValue _hint;
3941
private TimeSpan? _maxTime;
4042
private readonly MessageEncoderSettings _messageEncoderSettings;
4143
private readonly IReadOnlyList<BsonDocument> _pipeline;
@@ -105,6 +107,30 @@ public CollectionNamespace CollectionNamespace
105107
get { return _collectionNamespace; }
106108
}
107109

110+
/// <summary>
111+
/// Gets or sets the comment.
112+
/// </summary>
113+
/// <value>
114+
/// The comment.
115+
/// </value>
116+
public string Comment
117+
{
118+
get { return _comment; }
119+
set { _comment = value; }
120+
}
121+
122+
/// <summary>
123+
/// Gets or sets the hint. This must either be a BsonString representing the index name or a BsonDocument representing the key pattern of the index.
124+
/// </summary>
125+
/// <value>
126+
/// The hint.
127+
/// </value>
128+
public BsonValue Hint
129+
{
130+
get { return _hint; }
131+
set { _hint = value; }
132+
}
133+
108134
/// <summary>
109135
/// Gets or sets the maximum time the server should spend on this operation.
110136
/// </summary>
@@ -197,7 +223,9 @@ internal BsonDocument CreateCommand(SemanticVersion serverVersion)
197223
{ "maxTimeMS", () => _maxTime.Value.TotalMilliseconds, _maxTime.HasValue },
198224
{ "collation", () => _collation.ToBsonDocument(), _collation != null },
199225
{ "writeConcern", () => _writeConcern.ToBsonDocument(), Feature.CommandsThatWriteAcceptWriteConcern.ShouldSendWriteConcern(serverVersion, _writeConcern) },
200-
{ "cursor", new BsonDocument(), serverVersion >= new SemanticVersion(3, 5, 0) }
226+
{ "cursor", new BsonDocument(), serverVersion >= new SemanticVersion(3, 5, 0) },
227+
{ "hint", () => _hint, _hint != null },
228+
{ "comment", () => _comment, _comment != null }
201229
};
202230
}
203231

src/MongoDB.Driver/AggregateOptions.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515

1616
using System;
17+
using MongoDB.Bson;
1718
using MongoDB.Driver.Core.Misc;
1819

1920
namespace MongoDB.Driver
@@ -28,6 +29,8 @@ public class AggregateOptions
2829
private int? _batchSize;
2930
private bool? _bypassDocumentValidation;
3031
private Collation _collation;
32+
private string _comment;
33+
private BsonValue _hint;
3134
private TimeSpan? _maxAwaitTime;
3235
private TimeSpan? _maxTime;
3336
private ExpressionTranslationOptions _translationOptions;
@@ -70,6 +73,24 @@ public Collation Collation
7073
set { _collation = value; }
7174
}
7275

76+
/// <summary>
77+
/// Gets or sets the comment.
78+
/// </summary>
79+
public string Comment
80+
{
81+
get { return _comment; }
82+
set { _comment = value; }
83+
}
84+
85+
/// <summary>
86+
/// Gets or sets the hint. This must either be a BsonString representing the index name or a BsonDocument representing the key pattern of the index.
87+
/// </summary>
88+
public BsonValue Hint
89+
{
90+
get { return _hint; }
91+
set { _hint = value; }
92+
}
93+
7394
/// <summary>
7495
/// Gets or sets the maximum await time.
7596
/// </summary>

src/MongoDB.Driver/MongoCollectionImpl.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,8 @@ private AggregateOperation<TResult> CreateAggregateOperation<TResult>(RenderedPi
652652
AllowDiskUse = options.AllowDiskUse,
653653
BatchSize = options.BatchSize,
654654
Collation = options.Collation,
655+
Comment = options.Comment,
656+
Hint = options.Hint,
655657
MaxAwaitTime = options.MaxAwaitTime,
656658
MaxTime = options.MaxTime,
657659
ReadConcern = _settings.ReadConcern,
@@ -685,6 +687,8 @@ private AggregateToCollectionOperation CreateAggregateToCollectionOperation<TRes
685687
AllowDiskUse = options.AllowDiskUse,
686688
BypassDocumentValidation = options.BypassDocumentValidation,
687689
Collation = options.Collation,
690+
Comment = options.Comment,
691+
Hint = options.Hint,
688692
MaxTime = options.MaxTime,
689693
WriteConcern = _settings.WriteConcern
690694
};

tests/MongoDB.Driver.Core.Tests/Core/Operations/AggregateExplainOperationTests.cs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,30 @@ public void Collation_get_and_set_should_work()
9393
result.Should().BeSameAs(value);
9494
}
9595

96+
[Fact]
97+
public void Comment_get_and_set_should_work()
98+
{
99+
var subject = new AggregateExplainOperation(_collectionNamespace, __pipeline, _messageEncoderSettings);
100+
var value = "test";
101+
102+
subject.Comment = value;
103+
var result = subject.Comment;
104+
105+
result.Should().BeSameAs(value);
106+
}
107+
108+
[Fact]
109+
public void Hint_get_and_set_should_work()
110+
{
111+
var subject = new AggregateExplainOperation(_collectionNamespace, __pipeline, _messageEncoderSettings);
112+
var value = new BsonDocument("x", 1);
113+
114+
subject.Hint = value;
115+
var result = subject.Hint;
116+
117+
result.Should().BeSameAs(value);
118+
}
119+
96120
[Fact]
97121
public void MaxTime_get_and_set_should_work()
98122
{
@@ -168,6 +192,53 @@ public void CreateCommand_should_return_expected_result_when_Collation_is_set(
168192
result.Should().Be(expectedResult);
169193
}
170194

195+
[Theory]
196+
[ParameterAttributeData]
197+
public void CreateCommand_should_return_expected_result_when_Comment_is_set(
198+
[Values(null, "test")]
199+
string comment)
200+
{
201+
var subject = new AggregateExplainOperation(_collectionNamespace, __pipeline, _messageEncoderSettings)
202+
{
203+
Comment = comment,
204+
};
205+
206+
var result = subject.CreateCommand(null);
207+
208+
var expectedResult = new BsonDocument
209+
{
210+
{ "aggregate", _collectionNamespace.CollectionName },
211+
{ "explain", true },
212+
{ "pipeline", new BsonArray(__pipeline) },
213+
{ "comment", () => comment, comment != null }
214+
};
215+
result.Should().Be(expectedResult);
216+
}
217+
218+
[Theory]
219+
[ParameterAttributeData]
220+
public void CreateCommand_should_return_the_expected_result_when_Hint_is_set(
221+
[Values(null, "{x: 1}")]
222+
string hintJson)
223+
{
224+
var hint = hintJson == null ? null : BsonDocument.Parse(hintJson);
225+
var subject = new AggregateExplainOperation(_collectionNamespace, __pipeline, _messageEncoderSettings)
226+
{
227+
Hint = hint
228+
};
229+
230+
var result = subject.CreateCommand(null);
231+
232+
var expectedResult = new BsonDocument
233+
{
234+
{ "aggregate", _collectionNamespace.CollectionName },
235+
{ "explain", true },
236+
{ "pipeline", new BsonArray(__pipeline) },
237+
{ "hint", () => hint, hint != null }
238+
};
239+
result.Should().Be(expectedResult);
240+
}
241+
171242
[SkippableTheory]
172243
[ParameterAttributeData]
173244
public void CreateCommand_should_return_expected_result_when_MaxTime_is_set(
@@ -270,6 +341,49 @@ public void Execute_should_throw_when_Collation_is_set_but_not_supported(
270341
exception.Should().BeOfType<NotSupportedException>();
271342
}
272343

344+
[SkippableTheory]
345+
[ParameterAttributeData]
346+
public void Execute_should_return_expected_result_when_Comment_is_set(
347+
[Values(false, true)]
348+
bool async)
349+
{
350+
RequireServer.Check()
351+
.ClusterTypes(ClusterType.Standalone, ClusterType.ReplicaSet)
352+
.Supports(Feature.AggregateExplain, Feature.AggregateComment);
353+
var subject = new AggregateExplainOperation(_collectionNamespace, __pipeline, _messageEncoderSettings)
354+
{
355+
Comment = "test"
356+
};
357+
358+
using (var profile = Profile(_collectionNamespace.DatabaseNamespace))
359+
{
360+
var result = ExecuteOperation(subject, async);
361+
362+
result.Should().NotBeNull();
363+
364+
var profileEntries = profile.Find(new BsonDocument("command.aggregate", new BsonDocument("$exists", true)));
365+
profileEntries.Should().HaveCount(1);
366+
profileEntries[0]["command"]["comment"].AsString.Should().Be(subject.Comment);
367+
}
368+
}
369+
370+
[SkippableTheory]
371+
[ParameterAttributeData]
372+
public void Execute_should_return_expected_result_when_Hint_is_set(
373+
[Values(false, true)]
374+
bool async)
375+
{
376+
RequireServer.Check().Supports(Feature.AggregateExplain, Feature.AggregateHint);
377+
var subject = new AggregateExplainOperation(_collectionNamespace, __pipeline, _messageEncoderSettings)
378+
{
379+
Hint = "_id_"
380+
};
381+
382+
var result = ExecuteOperation(subject, async);
383+
384+
result.Should().NotBeNull();
385+
}
386+
273387
[SkippableTheory]
274388
[ParameterAttributeData]
275389
public void Execute_should_return_expected_result_when_MaxTime_is_set(

0 commit comments

Comments
 (0)