From 8cb9c3d8f0feda09877488c5ff9fc58fe9d04c54 Mon Sep 17 00:00:00 2001 From: Samir Boulema Date: Thu, 20 Jul 2023 10:37:29 +0200 Subject: [PATCH 1/4] CSHARP-4728: Add implementation for Atlas Search Sort --- src/MongoDB.Driver/AggregateFluent.cs | 3 ++- src/MongoDB.Driver/AggregateFluentBase.cs | 1 + src/MongoDB.Driver/IAggregateFluent.cs | 2 ++ src/MongoDB.Driver/Linq/MongoQueryable.cs | 4 +++- src/MongoDB.Driver/PipelineDefinitionBuilder.cs | 4 +++- .../PipelineStageDefinitionBuilder.cs | 3 +++ .../PipelineDefinitionBuilderTests.cs | 13 +++++++++++++ .../MongoDB.Driver.Tests/Search/AtlasSearchTests.cs | 13 +++++++++++++ 8 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/MongoDB.Driver/AggregateFluent.cs b/src/MongoDB.Driver/AggregateFluent.cs index 52db3ab89ef..154b929e022 100644 --- a/src/MongoDB.Driver/AggregateFluent.cs +++ b/src/MongoDB.Driver/AggregateFluent.cs @@ -244,10 +244,11 @@ public override IAggregateFluent Search( SearchHighlightOptions highlight = null, string indexName = null, SearchCountOptions count = null, + SortDefinition sort = null, bool returnStoredSource = false, bool scoreDetails = false) { - return WithPipeline(_pipeline.Search(searchDefinition, highlight, indexName, count, returnStoredSource, scoreDetails)); + return WithPipeline(_pipeline.Search(searchDefinition, highlight, indexName, count, sort, returnStoredSource, scoreDetails)); } public override IAggregateFluent SearchMeta( diff --git a/src/MongoDB.Driver/AggregateFluentBase.cs b/src/MongoDB.Driver/AggregateFluentBase.cs index 511eced50ec..21b0933271a 100644 --- a/src/MongoDB.Driver/AggregateFluentBase.cs +++ b/src/MongoDB.Driver/AggregateFluentBase.cs @@ -222,6 +222,7 @@ public virtual IAggregateFluent Search( SearchHighlightOptions highlight = null, string indexName = null, SearchCountOptions count = null, + SortDefinition sort = null, bool returnStoredSource = false, bool scoreDetails = false) { diff --git a/src/MongoDB.Driver/IAggregateFluent.cs b/src/MongoDB.Driver/IAggregateFluent.cs index 079f16d897d..e9bdf8d4dfb 100644 --- a/src/MongoDB.Driver/IAggregateFluent.cs +++ b/src/MongoDB.Driver/IAggregateFluent.cs @@ -361,6 +361,7 @@ IAggregateFluent SetWindowFields( /// The highlight options. /// The index name. /// The count options. + /// The sort specification. /// /// Flag that specifies whether to perform a full document lookup on the backend database /// or return only stored source fields directly from Atlas Search. @@ -375,6 +376,7 @@ IAggregateFluent Search( SearchHighlightOptions highlight = null, string indexName = null, SearchCountOptions count = null, + SortDefinition sort = null, bool returnStoredSource = false, bool scoreDetails = false); diff --git a/src/MongoDB.Driver/Linq/MongoQueryable.cs b/src/MongoDB.Driver/Linq/MongoQueryable.cs index ffee7be89d3..8b2781a25e1 100644 --- a/src/MongoDB.Driver/Linq/MongoQueryable.cs +++ b/src/MongoDB.Driver/Linq/MongoQueryable.cs @@ -1145,6 +1145,7 @@ public static IMongoQueryable Sample(this IMongoQueryableThe highlight options. /// The index name. /// The count options. + /// The sort specification. /// /// Flag that specifies whether to perform a full document lookup on the backend database /// or return only stored source fields directly from Atlas Search. @@ -1160,12 +1161,13 @@ public static IMongoQueryable Search( SearchHighlightOptions highlight = null, string indexName = null, SearchCountOptions count = null, + SortDefinition sort = null, bool returnStoredSource = false, bool scoreDetails = false) { return AppendStage( source, - PipelineStageDefinitionBuilder.Search(searchDefinition, highlight, indexName, count, returnStoredSource, scoreDetails)); + PipelineStageDefinitionBuilder.Search(searchDefinition, highlight, indexName, count, sort, returnStoredSource, scoreDetails)); } /// diff --git a/src/MongoDB.Driver/PipelineDefinitionBuilder.cs b/src/MongoDB.Driver/PipelineDefinitionBuilder.cs index 8c25fe5c2e3..9dde0701c6f 100644 --- a/src/MongoDB.Driver/PipelineDefinitionBuilder.cs +++ b/src/MongoDB.Driver/PipelineDefinitionBuilder.cs @@ -1175,6 +1175,7 @@ public static PipelineDefinition ReplaceWithThe highlight options. /// The index name. /// The count options. + /// The sort specification. /// /// Flag that specifies whether to perform a full document lookup on the backend database /// or return only stored source fields directly from Atlas Search. @@ -1192,11 +1193,12 @@ public static PipelineDefinition Search( SearchHighlightOptions highlight = null, string indexName = null, SearchCountOptions count = null, + SortDefinition sort = null, bool returnStoredSource = false, bool scoreDetails = false) { Ensure.IsNotNull(pipeline, nameof(pipeline)); - return pipeline.AppendStage(PipelineStageDefinitionBuilder.Search(searchDefinition, highlight, indexName, count, returnStoredSource, scoreDetails)); + return pipeline.AppendStage(PipelineStageDefinitionBuilder.Search(searchDefinition, highlight, indexName, count, sort, returnStoredSource, scoreDetails)); } /// diff --git a/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs b/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs index 6ef9e68c111..9a06bc61245 100644 --- a/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs +++ b/src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs @@ -1316,6 +1316,7 @@ public static PipelineStageDefinition Project( /// The highlight options. /// The index name. /// The count options. + /// The sort specification. /// /// Flag that specifies whether to perform a full document lookup on the backend database /// or return only stored source fields directly from Atlas Search. @@ -1330,6 +1331,7 @@ public static PipelineStageDefinition Search( SearchHighlightOptions highlight = null, string indexName = null, SearchCountOptions count = null, + SortDefinition sort = null, bool returnStoredSource = false, bool scoreDetails = false) { @@ -1343,6 +1345,7 @@ public static PipelineStageDefinition Search( var renderedSearchDefinition = searchDefinition.Render(s, sr); renderedSearchDefinition.Add("highlight", () => highlight.Render(s, sr), highlight != null); renderedSearchDefinition.Add("count", () => count.Render(), count != null); + renderedSearchDefinition.Add("sort", () => sort.Render(s, sr), sort != null); renderedSearchDefinition.Add("index", indexName, indexName != null); renderedSearchDefinition.Add("returnStoredSource", returnStoredSource, returnStoredSource); renderedSearchDefinition.Add("scoreDetails", scoreDetails, scoreDetails); diff --git a/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs b/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs index 384f28dc28b..66648cd9502 100644 --- a/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs +++ b/tests/MongoDB.Driver.Tests/PipelineDefinitionBuilderTests.cs @@ -194,6 +194,19 @@ public void Search_should_add_expected_stage_with_score_details() stages[0].Should().Be("{ $search: { text: { query: 'foo', path: 'bar' }, scoreDetails: true } }"); } + [Fact] + public void Search_should_add_expected_stage_with_sort() + { + var pipeline = new EmptyPipelineDefinition(); + var builder = new SearchDefinitionBuilder(); + var sortBuilder = new SortDefinitionBuilder(); + + var result = pipeline.Search(builder.Text("bar", "foo"), sort: sortBuilder.Ascending("foo")); + + var stages = RenderStages(result, BsonDocumentSerializer.Instance); + stages[0].Should().Be("{ $search: { text: { query: 'foo', path: 'bar' }, sort: { 'foo': 1 } } }"); + } + [Fact] public void Search_should_throw_when_pipeline_is_null() { diff --git a/tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs b/tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs index dd8a52ec5a7..5e8f08a7371 100644 --- a/tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs +++ b/tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs @@ -112,6 +112,19 @@ public void Count_total() results.Should().ContainSingle().Which.MetaResult.Count.Total.Should().Be(108); } + [Fact] + public void Sort() + { + var results = GetTestCollection().Aggregate() + .Search( + Builders.Search.Text(x => x.Body, "liberty"), + sort: Builders.Sort.Descending(x => x.Title)) + .Project(Builders.Projection.Include(x => x.Title)) + .Limit(1) + .ToList(); + results.Should().ContainSingle().Which.Title.Should().Be("Gettysburg Address"); + } + [Fact] public void Exists() { From b1bd34051240c7b3c67cb7a104062eba84c5e907 Mon Sep 17 00:00:00 2001 From: Samir Boulema Date: Wed, 26 Jul 2023 10:01:22 +0200 Subject: [PATCH 2/4] CSHARP-4728: Resolve BorisDog comments --- .../Search/AtlasSearchTests.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs b/tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs index 5e8f08a7371..e91c35bdad3 100644 --- a/tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs +++ b/tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs @@ -112,19 +112,6 @@ public void Count_total() results.Should().ContainSingle().Which.MetaResult.Count.Total.Should().Be(108); } - [Fact] - public void Sort() - { - var results = GetTestCollection().Aggregate() - .Search( - Builders.Search.Text(x => x.Body, "liberty"), - sort: Builders.Sort.Descending(x => x.Title)) - .Project(Builders.Projection.Include(x => x.Title)) - .Limit(1) - .ToList(); - results.Should().ContainSingle().Which.Title.Should().Be("Gettysburg Address"); - } - [Fact] public void Exists() { @@ -415,6 +402,19 @@ public void SearchMeta_facet() bucket.Count.Should().Be(108); } + [Fact] + public void Sort() + { + var results = GetTestCollection().Aggregate() + .Search( + Builders.Search.Text(x => x.Body, "liberty"), + sort: Builders.Sort.Descending(x => x.Title)) + .Project(Builders.Projection.Include(x => x.Title)) + .Limit(1) + .ToList(); + results.Should().ContainSingle().Which.Title.Should().Be("US Constitution"); + } + [Fact] public void Should() { From 389262578c6318df8ef62d979139e0aca9dc1a7f Mon Sep 17 00:00:00 2001 From: Samir Boulema Date: Wed, 26 Jul 2023 20:12:10 +0200 Subject: [PATCH 3/4] CSHARP-4728: Resolve BorisDog comments 2 --- .../Search/AtlasSearchTests.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs b/tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs index e91c35bdad3..794aa075fbd 100644 --- a/tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs +++ b/tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs @@ -402,6 +402,17 @@ public void SearchMeta_facet() bucket.Count.Should().Be(108); } + [Fact] + public void Should() + { + var result = SearchSingle( + Builders.Search.Compound().Should( + Builders.Search.Phrase(x => x.Body, "life, liberty"), + Builders.Search.Wildcard(x => x.Body, "happ*", true)) + .MinimumShouldMatch(2)); + result.Title.Should().Be("Declaration of Independence"); + } + [Fact] public void Sort() { @@ -415,17 +426,6 @@ public void Sort() results.Should().ContainSingle().Which.Title.Should().Be("US Constitution"); } - [Fact] - public void Should() - { - var result = SearchSingle( - Builders.Search.Compound().Should( - Builders.Search.Phrase(x => x.Body, "life, liberty"), - Builders.Search.Wildcard(x => x.Body, "happ*", true)) - .MinimumShouldMatch(2)); - result.Title.Should().Be("Declaration of Independence"); - } - [Theory] [InlineData("first")] [InlineData("near")] From 0228932f66df639ee69cb1e7afd26ed5b51f7b2c Mon Sep 17 00:00:00 2001 From: Samir Boulema Date: Wed, 26 Jul 2023 23:07:38 +0200 Subject: [PATCH 4/4] Resolve BorisDog comments 3 --- tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs b/tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs index 794aa075fbd..529866abeb7 100644 --- a/tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs +++ b/tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs @@ -232,7 +232,7 @@ public void MustNot() var result = SearchSingle( Builders.Search.Compound().MustNot( Builders.Search.Phrase(x => x.Body, "life, liberty"))); - result.Title.Should().Be("US Constitution"); + result.Title.Should().Be("Gettysburg Address"); } [Fact]