Repository navigation
NCBC-4326: Add custom score and filter search queries #239
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
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
cfb21e1
NCBC-4326: Add custom score and filter search queries
davidkelly 3f66914
NCBC-4326: Read Boolean options from the nested query in the performer
davidkelly 6d00bb2
NCBC-4326: Reject custom queries with no inner query in the performer
davidkelly 7316ffa
NCBC-4326: Address review feedback on the custom script queries
davidkelly File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
128 changes: 128 additions & 0 deletions
128
src/Couchbase/Search/Queries/Script/CustomFilterQuery.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| #nullable enable | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Diagnostics.CodeAnalysis; | ||
| using Couchbase.Core.Compatibility; | ||
| using Newtonsoft.Json.Linq; | ||
|
|
||
| namespace Couchbase.Search.Queries.Script | ||
| { | ||
| /// <summary> | ||
| /// A query that passes the results of an inner query through a user-defined JavaScript filtering function. | ||
| /// Only the results for which the function returns true are kept. Their scores are not changed. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// <para> | ||
| /// Requires Couchbase Server 8.5.0 or later, Enterprise Edition. Custom script queries are disabled on the | ||
| /// Search service by default; enable them by setting <c>customScriptQueriesEnabled</c> to <c>"true"</c> with | ||
| /// <c>PUT /api/managerOptions</c> on a Search node. The SDK cannot detect this setting, so while it is disabled | ||
| /// the server rejects the query. Not available over couchbase2://. | ||
| /// </para> | ||
| /// <para> | ||
| /// The function is called once for each result, with <c>doc</c> and <c>params</c>: | ||
| /// <list type="bullet"> | ||
| /// <item><description><c>doc._id</c>: the document ID.</description></item> | ||
| /// <item><description><c>doc.score</c>: the score from the inner query.</description></item> | ||
| /// <item><description><c>doc.fields</c>: only the fields requested with <see cref="Fields"/>; undefined if | ||
| /// none are requested. See <see cref="Fields"/> for how text values appear.</description></item> | ||
| /// <item><description><c>params</c>: the object given to <see cref="Parameters"/>, the same for every | ||
| /// result; <c>null</c> if none is given.</description></item> | ||
| /// </list> | ||
| /// An exception in the function fails the whole query. | ||
| /// </para> | ||
| /// </remarks> | ||
| [InterfaceStability(Level.Uncommitted)] | ||
| public sealed class CustomFilterQuery : ISearchQuery | ||
| { | ||
| private readonly CustomScriptQuery _query; | ||
|
|
||
| /// <summary> | ||
| /// Creates a <see cref="CustomFilterQuery"/>. | ||
| /// </summary> | ||
| /// <param name="query">The inner query whose results are passed through the filtering function.</param> | ||
| /// <param name="source"> | ||
| /// A JavaScript function that takes <c>(doc, params)</c> and returns a boolean, for example | ||
| /// <c>function filter(doc, params) { return doc.score >= 0.5; }</c>. | ||
| /// </param> | ||
| public CustomFilterQuery(ISearchQuery query, string source) | ||
| { | ||
| _query = new CustomScriptQuery(query, source); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// The document fields made available to the filtering function, as <c>doc.fields</c>. | ||
| /// The function sees no fields unless this is set. Pass <c>"*"</c> for all fields. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// The values come from the Search index, not from the stored document, so a field must be indexed to be | ||
| /// available. Text values are the terms from the field's analyzer, not the original text. Use the | ||
| /// <c>keyword</c> analyzer to get the exact text. | ||
| /// </remarks> | ||
| /// <returns>This <see cref="CustomFilterQuery"/> for chaining.</returns> | ||
| public CustomFilterQuery Fields(params string[] fields) | ||
| { | ||
| _query.SetFields(fields); | ||
| return this; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Parameters made available to the filtering function, as <c>params</c>. | ||
| /// Values may be any JSON-serializable value, including nested dictionaries and lists. | ||
| /// The same parameters are given to the function for every result. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// The values are serialized with Newtonsoft.Json, not with the cluster's serializer. Use plain .NET values; | ||
| /// System.Text.Json types such as <c>JsonElement</c> are not serialized correctly. | ||
| /// </remarks> | ||
| /// <returns>This <see cref="CustomFilterQuery"/> for chaining.</returns> | ||
| public CustomFilterQuery Parameters(IDictionary<string, object?> parameters) | ||
| { | ||
| _query.SetParameters(parameters); | ||
| return this; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Has no effect. The Search service ignores a boost on this query type, so apply the boost to the inner | ||
| /// query instead. | ||
| /// </summary> | ||
| /// <returns>This <see cref="CustomFilterQuery"/>, unchanged.</returns> | ||
| [Obsolete("CustomFilterQuery does not support boost. Apply the boost to the inner query instead.")] | ||
| public ISearchQuery Boost(double boost) => this; | ||
|
|
||
| [RequiresUnreferencedCode(SearchClient.SearchRequiresUnreferencedMembersWarning)] | ||
| [RequiresDynamicCode(SearchClient.SearchRequiresDynamicCodeWarning)] | ||
| public JObject Export() => _query.Export("custom_filter"); | ||
|
|
||
| public ReadOnly AsReadOnly() => | ||
| new(_query.Query, _query.Source, _query.Fields, _query.Parameters); | ||
|
|
||
| public record ReadOnly( | ||
| ISearchQuery Query, | ||
| string Source, | ||
| IReadOnlyList<string>? Fields, | ||
| IReadOnlyDictionary<string, object?>? Parameters); | ||
| } | ||
| } | ||
|
|
||
| #region [ License information ] | ||
|
|
||
| /* ************************************************************ | ||
| * | ||
| * @author Couchbase <info@couchbase.com> | ||
| * @copyright 2026 Couchbase, Inc. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| * | ||
| * ************************************************************/ | ||
|
|
||
| #endregion |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.