-
Notifications
You must be signed in to change notification settings - Fork 1.3k
CSHARP-5769: Implement hasAncestor, hasRoot, and returnScope for Atlas Search #1933
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1437,16 +1437,53 @@ public static PipelineStageDefinition<TInput, TInput> Search<TInput>( | |
| public static PipelineStageDefinition<TInput, TInput> Search<TInput>( | ||
| SearchDefinition<TInput> searchDefinition, | ||
| SearchOptions<TInput> searchOptions) | ||
| => Search<TInput, TInput>(searchDefinition, returnScope: null, searchOptions); | ||
|
|
||
| /// <summary> | ||
| /// Creates a $search stage. | ||
| /// </summary> | ||
| /// <typeparam name="TInput">The type of the input documents.</typeparam> | ||
| /// <typeparam name="TOutput">The type of the output documents.</typeparam> | ||
| /// <param name="searchDefinition">The search definition.</param> | ||
| /// <param name="returnScope">The level of nested documents to return.</param> | ||
| /// <param name="searchOptions">The search options.</param> | ||
| /// <returns>The stage.</returns> | ||
| public static PipelineStageDefinition<TInput, TOutput> Search<TInput, TOutput>( | ||
| SearchDefinition<TInput> searchDefinition, | ||
| FieldDefinition<TInput, IEnumerable<TOutput>> returnScope, | ||
| SearchOptions<TInput> searchOptions) | ||
| { | ||
ajcvickers marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Ensure.IsNotNull(searchDefinition, nameof(searchDefinition)); | ||
|
|
||
| searchOptions ??= new SearchOptions<TInput>(); | ||
|
|
||
| const string operatorName = "$search"; | ||
| var stage = new DelegatedPipelineStageDefinition<TInput, TInput>( | ||
| var stage = new DelegatedPipelineStageDefinition<TInput, TOutput>( | ||
| operatorName, | ||
| args => | ||
| { | ||
| ClientSideProjectionHelper.ThrowIfClientSideProjection(args.DocumentSerializer, operatorName); | ||
| var renderedSearchDefinition = searchDefinition.Render(args); | ||
|
|
||
| IBsonSerializer<TOutput> outputSerializer; | ||
| if (returnScope == null) | ||
| { | ||
| if (typeof(TOutput) != typeof(TInput)) | ||
| { | ||
| throw new InvalidOperationException( | ||
| $"The search output type '{typeof(TOutput).Name}' must be the same as the input type '{typeof(TInput).Name}' when 'returnScope' is not specified. Use the overload that specifies 'returnScope' to return documents of a nested collection type."); | ||
| } | ||
|
|
||
| outputSerializer = (IBsonSerializer<TOutput>)args.DocumentSerializer; | ||
| } | ||
ajcvickers marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| else | ||
| { | ||
| outputSerializer = args.SerializerRegistry.GetSerializer<TOutput>(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As far as I understood the returnScope is a path inside of the parent document. In such case we have a little more info to resolve the proper serializer. Instead of Lookup, we can try to get member info if DocumentSerializer is IBsonDocumentSerializer. See TryGetMemberSerializationInfo method. |
||
| renderedSearchDefinition.Add("returnScope", new BsonDocument { { "path", returnScope.Render(args).FieldName } }); | ||
| searchOptions = searchOptions.Clone(); | ||
| searchOptions.ReturnStoredSource = true; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure if I like the idea to alter user's provided options silently. I know it's a clone. But may be we should simply document it "if your search request uses returnScope, make sure to set ReturnStoredSource to true." BTW, why do we need to set it to true? Does it described somewhere?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also am I right to think that we need all this clone-and-update stuff, only to use in like a 10 lines of code under? May be we can have a local variable instead? |
||
| } | ||
ajcvickers marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| renderedSearchDefinition.Add("highlight", () => searchOptions.Highlight.Render(args), searchOptions.Highlight != null); | ||
| renderedSearchDefinition.Add("count", () => searchOptions.CountOptions.Render(), searchOptions.CountOptions != null); | ||
| renderedSearchDefinition.Add("sort", () => searchOptions.Sort.Render(args), searchOptions.Sort != null); | ||
|
|
@@ -1458,7 +1495,7 @@ public static PipelineStageDefinition<TInput, TInput> Search<TInput>( | |
| renderedSearchDefinition.Add("searchBefore", () => searchOptions.SearchBefore, searchOptions.SearchBefore != null); | ||
|
|
||
| var document = new BsonDocument(operatorName, renderedSearchDefinition); | ||
| return new RenderedPipelineStageDefinition<TInput>(operatorName, document, args.DocumentSerializer); | ||
| return new RenderedPipelineStageDefinition<TOutput>(operatorName, document, outputSerializer); | ||
| }); | ||
|
|
||
| return stage; | ||
|
|
@@ -1476,6 +1513,22 @@ public static PipelineStageDefinition<TInput, SearchMetaResult> SearchMeta<TInpu | |
| SearchDefinition<TInput> searchDefinition, | ||
| string indexName = null, | ||
| SearchCountOptions count = null) | ||
| => SearchMeta(searchDefinition, returnScope: null, indexName, count); | ||
|
|
||
| /// <summary> | ||
| /// Creates a $searchMeta stage. | ||
| /// </summary> | ||
| /// <typeparam name="TInput">The type of the input documents.</typeparam> | ||
| /// <param name="searchDefinition">The search definition.</param> | ||
| /// <param name="returnScope">The level of nested documents to return.</param> | ||
| /// <param name="indexName">The index name.</param> | ||
| /// <param name="count">The count options.</param> | ||
| /// <returns>The stage.</returns> | ||
| public static PipelineStageDefinition<TInput, SearchMetaResult> SearchMeta<TInput>( | ||
| SearchDefinition<TInput> searchDefinition, | ||
| FieldDefinition<TInput> returnScope, | ||
| string indexName = null, | ||
| SearchCountOptions count = null) | ||
| { | ||
| Ensure.IsNotNull(searchDefinition, nameof(searchDefinition)); | ||
|
|
||
|
|
@@ -1488,6 +1541,7 @@ public static PipelineStageDefinition<TInput, SearchMetaResult> SearchMeta<TInpu | |
| var renderedSearchDefinition = searchDefinition.Render(args); | ||
| renderedSearchDefinition.Add("count", () => count.Render(), count != null); | ||
| renderedSearchDefinition.Add("index", indexName, indexName != null); | ||
| renderedSearchDefinition.Add("returnScope", () => new BsonDocument { { "path", returnScope!.Render(args).FieldName } }, returnScope != null); | ||
|
|
||
| var document = new BsonDocument(operatorName, renderedSearchDefinition); | ||
| return new RenderedPipelineStageDefinition<SearchMetaResult>( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like not necessary change.