Skip to content

Commit 628577e

Browse files
authored
CSHARP-4732: Add SearchOptions overload to Search API (#1149)
1 parent a7c27df commit 628577e

File tree

9 files changed

+172
-23
lines changed

9 files changed

+172
-23
lines changed

src/MongoDB.Driver/AggregateFluent.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,26 @@ public override IAggregateFluent<TResult> Search(
244244
SearchHighlightOptions<TResult> highlight = null,
245245
string indexName = null,
246246
SearchCountOptions count = null,
247-
SortDefinition<TResult> sort = null,
248247
bool returnStoredSource = false,
249248
bool scoreDetails = false)
250249
{
251-
return WithPipeline(_pipeline.Search(searchDefinition, highlight, indexName, count, sort, returnStoredSource, scoreDetails));
250+
var searchOptions = new SearchOptions<TResult>()
251+
{
252+
CountOptions = count,
253+
Highlight = highlight,
254+
IndexName = indexName,
255+
ReturnStoredSource = returnStoredSource,
256+
ScoreDetails = scoreDetails
257+
};
258+
259+
return WithPipeline(_pipeline.Search(searchDefinition, searchOptions));
260+
}
261+
262+
public override IAggregateFluent<TResult> Search(
263+
SearchDefinition<TResult> searchDefinition,
264+
SearchOptions<TResult> searchOptions)
265+
{
266+
return WithPipeline(_pipeline.Search(searchDefinition, searchOptions));
252267
}
253268

254269
public override IAggregateFluent<SearchMetaResult> SearchMeta(

src/MongoDB.Driver/AggregateFluentBase.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,13 +222,20 @@ public virtual IAggregateFluent<TResult> Search(
222222
SearchHighlightOptions<TResult> highlight = null,
223223
string indexName = null,
224224
SearchCountOptions count = null,
225-
SortDefinition<TResult> sort = null,
226225
bool returnStoredSource = false,
227226
bool scoreDetails = false)
228227
{
229228
throw new NotImplementedException();
230229
}
231230

231+
/// <inheritdoc />
232+
public virtual IAggregateFluent<TResult> Search(
233+
SearchDefinition<TResult> searchDefinition,
234+
SearchOptions<TResult> searchOptions)
235+
{
236+
throw new NotImplementedException();
237+
}
238+
232239
/// <inheritdoc />
233240
public virtual IAggregateFluent<SearchMetaResult> SearchMeta(
234241
SearchDefinition<TResult> searchDefinition,

src/MongoDB.Driver/IAggregateFluent.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,25 +361,35 @@ IAggregateFluent<BsonDocument> SetWindowFields<TWindowFields>(
361361
/// <param name="highlight">The highlight options.</param>
362362
/// <param name="indexName">The index name.</param>
363363
/// <param name="count">The count options.</param>
364-
/// <param name="sort">The sort specification.</param>
365364
/// <param name="returnStoredSource">
366365
/// Flag that specifies whether to perform a full document lookup on the backend database
367366
/// or return only stored source fields directly from Atlas Search.
368367
/// </param>
369368
/// <param name="scoreDetails">
370369
/// Flag that specifies whether to return a detailed breakdown
371-
/// of the score for each document in the result.
370+
/// of the score for each document in the result.
372371
/// </param>
373372
/// <returns>The fluent aggregate interface.</returns>
374373
IAggregateFluent<TResult> Search(
375374
SearchDefinition<TResult> searchDefinition,
376375
SearchHighlightOptions<TResult> highlight = null,
377376
string indexName = null,
378377
SearchCountOptions count = null,
379-
SortDefinition<TResult> sort = null,
380378
bool returnStoredSource = false,
381379
bool scoreDetails = false);
382380

381+
/// <summary>
382+
/// Appends a $search stage to the pipeline.
383+
/// </summary>
384+
/// <param name="searchDefinition">The search definition.</param>
385+
/// <param name="searchOptions">The search options.</param>
386+
/// <returns>
387+
/// The fluent aggregate interface.
388+
/// </returns>
389+
IAggregateFluent<TResult> Search(
390+
SearchDefinition<TResult> searchDefinition,
391+
SearchOptions<TResult> searchOptions);
392+
383393
/// <summary>
384394
/// Appends a $searchMeta stage to the pipeline.
385395
/// </summary>

src/MongoDB.Driver/Linq/MongoQueryable.cs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,7 +1145,6 @@ public static IMongoQueryable<TSource> Sample<TSource>(this IMongoQueryable<TSou
11451145
/// <param name="highlight">The highlight options.</param>
11461146
/// <param name="indexName">The index name.</param>
11471147
/// <param name="count">The count options.</param>
1148-
/// <param name="sort">The sort specification.</param>
11491148
/// <param name="returnStoredSource">
11501149
/// Flag that specifies whether to perform a full document lookup on the backend database
11511150
/// or return only stored source fields directly from Atlas Search.
@@ -1161,13 +1160,37 @@ public static IMongoQueryable<TSource> Search<TSource>(
11611160
SearchHighlightOptions<TSource> highlight = null,
11621161
string indexName = null,
11631162
SearchCountOptions count = null,
1164-
SortDefinition<TSource> sort = null,
11651163
bool returnStoredSource = false,
11661164
bool scoreDetails = false)
1165+
{
1166+
var searchOptions = new SearchOptions<TSource>()
1167+
{
1168+
CountOptions = count,
1169+
Highlight = highlight,
1170+
IndexName = indexName,
1171+
ReturnStoredSource = returnStoredSource,
1172+
ScoreDetails = scoreDetails
1173+
};
1174+
1175+
return Search(source, searchDefinition, searchOptions);
1176+
}
1177+
1178+
/// <summary>
1179+
/// Appends a $search stage to the LINQ pipeline.
1180+
/// </summary>
1181+
/// <typeparam name="TSource">The type of the elements of <paramref name="source" />.</typeparam>
1182+
/// <param name="source">A sequence of values.</param>
1183+
/// <param name="searchDefinition">The search definition.</param>
1184+
/// <param name="searchOptions">The search options.</param>
1185+
/// <returns>The queryable with a new stage appended.</returns>
1186+
public static IMongoQueryable<TSource> Search<TSource>(
1187+
this IMongoQueryable<TSource> source,
1188+
SearchDefinition<TSource> searchDefinition,
1189+
SearchOptions<TSource> searchOptions)
11671190
{
11681191
return AppendStage(
11691192
source,
1170-
PipelineStageDefinitionBuilder.Search(searchDefinition, highlight, indexName, count, sort, returnStoredSource, scoreDetails));
1193+
PipelineStageDefinitionBuilder.Search(searchDefinition, searchOptions));
11711194
}
11721195

11731196
/// <summary>

src/MongoDB.Driver/PipelineDefinitionBuilder.cs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,7 +1175,6 @@ public static PipelineDefinition<TInput, TOutput> ReplaceWith<TInput, TIntermedi
11751175
/// <param name="highlight">The highlight options.</param>
11761176
/// <param name="indexName">The index name.</param>
11771177
/// <param name="count">The count options.</param>
1178-
/// <param name="sort">The sort specification.</param>
11791178
/// <param name="returnStoredSource">
11801179
/// Flag that specifies whether to perform a full document lookup on the backend database
11811180
/// or return only stored source fields directly from Atlas Search.
@@ -1193,12 +1192,31 @@ public static PipelineDefinition<TInput, TOutput> Search<TInput, TOutput>(
11931192
SearchHighlightOptions<TOutput> highlight = null,
11941193
string indexName = null,
11951194
SearchCountOptions count = null,
1196-
SortDefinition<TOutput> sort = null,
11971195
bool returnStoredSource = false,
11981196
bool scoreDetails = false)
11991197
{
12001198
Ensure.IsNotNull(pipeline, nameof(pipeline));
1201-
return pipeline.AppendStage(PipelineStageDefinitionBuilder.Search(searchDefinition, highlight, indexName, count, sort, returnStoredSource, scoreDetails));
1199+
return pipeline.AppendStage(PipelineStageDefinitionBuilder.Search(searchDefinition, highlight, indexName, count, returnStoredSource, scoreDetails));
1200+
}
1201+
1202+
/// <summary>
1203+
/// Appends a $search stage to the pipeline.
1204+
/// </summary>
1205+
/// <typeparam name="TInput">The type of the input documents.</typeparam>
1206+
/// <typeparam name="TOutput">The type of the output documents.</typeparam>
1207+
/// <param name="pipeline">The pipeline.</param>
1208+
/// <param name="searchDefinition">The search definition.</param>
1209+
/// <param name="searchOptions">The search options.</param>
1210+
/// <returns>
1211+
/// A new pipeline with an additional stage.
1212+
/// </returns>
1213+
public static PipelineDefinition<TInput, TOutput> Search<TInput, TOutput>(
1214+
this PipelineDefinition<TInput, TOutput> pipeline,
1215+
SearchDefinition<TOutput> searchDefinition,
1216+
SearchOptions<TOutput> searchOptions)
1217+
{
1218+
Ensure.IsNotNull(pipeline, nameof(pipeline));
1219+
return pipeline.AppendStage(PipelineStageDefinitionBuilder.Search(searchDefinition, searchOptions));
12021220
}
12031221

12041222
/// <summary>

src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,7 +1316,6 @@ public static PipelineStageDefinition<TInput, TOutput> Project<TInput, TOutput>(
13161316
/// <param name="highlight">The highlight options.</param>
13171317
/// <param name="indexName">The index name.</param>
13181318
/// <param name="count">The count options.</param>
1319-
/// <param name="sort">The sort specification.</param>
13201319
/// <param name="returnStoredSource">
13211320
/// Flag that specifies whether to perform a full document lookup on the backend database
13221321
/// or return only stored source fields directly from Atlas Search.
@@ -1331,9 +1330,31 @@ public static PipelineStageDefinition<TInput, TInput> Search<TInput>(
13311330
SearchHighlightOptions<TInput> highlight = null,
13321331
string indexName = null,
13331332
SearchCountOptions count = null,
1334-
SortDefinition<TInput> sort = null,
13351333
bool returnStoredSource = false,
13361334
bool scoreDetails = false)
1335+
{
1336+
var searchOptions = new SearchOptions<TInput>()
1337+
{
1338+
CountOptions = count,
1339+
Highlight = highlight,
1340+
IndexName = indexName,
1341+
ReturnStoredSource = returnStoredSource,
1342+
ScoreDetails = scoreDetails
1343+
};
1344+
1345+
return Search(searchDefinition, searchOptions);
1346+
}
1347+
1348+
/// <summary>
1349+
/// Creates a $search stage.
1350+
/// </summary>
1351+
/// <typeparam name="TInput">The type of the input documents.</typeparam>
1352+
/// <param name="searchDefinition">The search definition.</param>
1353+
/// <param name="searchOptions">The search options.</param>
1354+
/// <returns>The stage.</returns>
1355+
public static PipelineStageDefinition<TInput, TInput> Search<TInput>(
1356+
SearchDefinition<TInput> searchDefinition,
1357+
SearchOptions<TInput> searchOptions)
13371358
{
13381359
Ensure.IsNotNull(searchDefinition, nameof(searchDefinition));
13391360

@@ -1343,12 +1364,12 @@ public static PipelineStageDefinition<TInput, TInput> Search<TInput>(
13431364
(s, sr, linqProvider) =>
13441365
{
13451366
var renderedSearchDefinition = searchDefinition.Render(s, sr);
1346-
renderedSearchDefinition.Add("highlight", () => highlight.Render(s, sr), highlight != null);
1347-
renderedSearchDefinition.Add("count", () => count.Render(), count != null);
1348-
renderedSearchDefinition.Add("sort", () => sort.Render(s, sr), sort != null);
1349-
renderedSearchDefinition.Add("index", indexName, indexName != null);
1350-
renderedSearchDefinition.Add("returnStoredSource", returnStoredSource, returnStoredSource);
1351-
renderedSearchDefinition.Add("scoreDetails", scoreDetails, scoreDetails);
1367+
renderedSearchDefinition.Add("highlight", () => searchOptions.Highlight.Render(s, sr), searchOptions.Highlight != null);
1368+
renderedSearchDefinition.Add("count", () => searchOptions.CountOptions.Render(), searchOptions.CountOptions != null);
1369+
renderedSearchDefinition.Add("sort", () => searchOptions.Sort.Render(s, sr), searchOptions.Sort != null);
1370+
renderedSearchDefinition.Add("index", searchOptions.IndexName, searchOptions.IndexName != null);
1371+
renderedSearchDefinition.Add("returnStoredSource", searchOptions.ReturnStoredSource, searchOptions.ReturnStoredSource);
1372+
renderedSearchDefinition.Add("scoreDetails", searchOptions.ScoreDetails, searchOptions.ScoreDetails);
13521373

13531374
var document = new BsonDocument(operatorName, renderedSearchDefinition);
13541375
return new RenderedPipelineStageDefinition<TInput>(operatorName, document, s);
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/* Copyright 2010-present MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
namespace MongoDB.Driver.Search
17+
{
18+
/// <summary>
19+
/// Options for search.
20+
/// </summary>
21+
public sealed class SearchOptions<TResult>
22+
{
23+
/// <summary>
24+
/// Gets or sets the options for counting the search results.
25+
/// </summary>
26+
public SearchCountOptions CountOptions { get; set; }
27+
28+
/// <summary>
29+
/// Gets or sets the options for highlighting.
30+
/// </summary>
31+
public SearchHighlightOptions<TResult> Highlight { get; set; }
32+
33+
/// <summary>
34+
/// Gets or sets the index name.
35+
/// </summary>
36+
public string IndexName { get; set; }
37+
38+
/// <summary>
39+
/// Gets or sets a flag that specifies whether to perform a full document lookup on the backend database
40+
/// or return only stored source fields directly from Atlas Search.
41+
/// </summary>
42+
public bool ReturnStoredSource { get; set; }
43+
44+
/// <summary>
45+
/// Gets or sets a flag that specifies whether to return a detailed breakdown
46+
/// of the score for each document in the result.
47+
/// </summary>
48+
public bool ScoreDetails { get; set; }
49+
50+
/// <summary>
51+
/// Gets or sets the sort specification.
52+
/// </summary>
53+
public SortDefinition<TResult> Sort { get; set; }
54+
}
55+
}

tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ public void Search_should_add_expected_stage_with_sort()
201201
var builder = new SearchDefinitionBuilder<BsonDocument>();
202202
var sortBuilder = new SortDefinitionBuilder<BsonDocument>();
203203

204-
var result = pipeline.Search(builder.Text("bar", "foo"), sort: sortBuilder.Ascending("foo"));
204+
var result = pipeline.Search(builder.Text("bar", "foo"), new() { Sort = sortBuilder.Ascending("foo") });
205205

206206
var stages = RenderStages(result, BsonDocumentSerializer.Instance);
207207
stages[0].Should().Be("{ $search: { text: { query: 'foo', path: 'bar' }, sort: { 'foo': 1 } } }");

tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ public void Sort()
420420
var results = GetTestCollection().Aggregate()
421421
.Search(
422422
Builders.Search.Text(x => x.Body, "liberty"),
423-
sort: Builders.Sort.Descending(x => x.Title))
423+
new() { Sort = Builders.Sort.Descending(x => x.Title) })
424424
.Project<HistoricalDocument>(Builders.Projection.Include(x => x.Title))
425425
.Limit(1)
426426
.ToList();
@@ -473,7 +473,7 @@ private HistoricalDocument SearchSingle(
473473
ProjectionDefinition<HistoricalDocument, HistoricalDocument> projectionDefinition = null,
474474
SortDefinition<HistoricalDocument> sort = null)
475475
{
476-
var fluent = GetTestCollection().Aggregate().Search(searchDefintion, sort: sort);
476+
var fluent = GetTestCollection().Aggregate().Search(searchDefintion, new() { Sort = sort });
477477

478478
if (projectionDefinition != null)
479479
{

0 commit comments

Comments
 (0)