From 588a9bc34411c78ce239db2980877a636903c341 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Wed, 3 Mar 2021 11:29:31 +0000 Subject: [PATCH] Add linear function to rank_feature query (#5373) * Add linear function to rank_feature query * Update docs and skip version in tests --- .../rank-feature-query-usage.asciidoc | 38 +++++++++++++++++++ .../RankFeature/RankFeatureQuery.cs | 34 ++++++++++++++++- .../RankFeature/RankFeatureQueryUsageTests.cs | 24 ++++++++++++ 3 files changed, 95 insertions(+), 1 deletion(-) diff --git a/docs/query-dsl/specialized/rank-feature/rank-feature-query-usage.asciidoc b/docs/query-dsl/specialized/rank-feature/rank-feature-query-usage.asciidoc index 1f08cde73fb..1ba516f4859 100644 --- a/docs/query-dsl/specialized/rank-feature/rank-feature-query-usage.asciidoc +++ b/docs/query-dsl/specialized/rank-feature/rank-feature-query-usage.asciidoc @@ -99,3 +99,41 @@ new RankFeatureQuery } ---- +==== Fluent DSL example + +[source,csharp] +---- +q +.RankFeature(rf => rf + .Name("named_query") + .Boost(1.1) + .Field(f => f.Rank) + .Linear()) +---- + +==== Object Initializer syntax example + +[source,csharp] +---- +new RankFeatureQuery +{ + Name = "named_query", + Boost = 1.1, + Field = Infer.Field(f => f.Rank), + Function = new RankFeatureLinearFunction() +} +---- + +[source,javascript] +.Example json output +---- +{ + "rank_feature": { + "_name": "named_query", + "boost": 1.1, + "field": "rank", + "linear": {} + } +} +---- + diff --git a/src/Nest/QueryDsl/Specialized/RankFeature/RankFeatureQuery.cs b/src/Nest/QueryDsl/Specialized/RankFeature/RankFeatureQuery.cs index eb54e82cd77..3f05382a541 100644 --- a/src/Nest/QueryDsl/Specialized/RankFeature/RankFeatureQuery.cs +++ b/src/Nest/QueryDsl/Specialized/RankFeature/RankFeatureQuery.cs @@ -54,6 +54,13 @@ public RankFeatureQueryDescriptor Logarithm(Func public RankFeatureQueryDescriptor Sigmoid(Func selector) => Assign(selector, (a, v) => a.Function = v?.Invoke(new RankFeatureSigmoidFunctionDescriptor())); + + /// + public RankFeatureQueryDescriptor Linear() + { + Self.Function = new RankFeatureLinearFunction(); + return this; + } } /// @@ -162,6 +169,24 @@ public class RankFeatureSigmoidFunctionDescriptor public RankFeatureSigmoidFunctionDescriptor Pivot(float pivot) => Assign(pivot, (a, v) => a.Pivot = v); } + /// + /// Gives a score equal to the indexed value of S, where S is the value of the rank feature field. + /// + /// If a rank feature field is indexed with "positive_score_impact": true, its indexed value is equal to S and rounded to preserve + /// only 9 significant bits for the precision. + /// + /// If a rank feature field is indexed with "positive_score_impact": false, its indexed value is equal to 1/S and rounded to + /// preserve only 9 significant bits for the precision. + /// + public interface IRankFeatureLinearFunction : IRankFeatureFunction + { + } + + /// + public class RankFeatureLinearFunction : IRankFeatureLinearFunction + { + } + internal class RankFeatureQueryFormatter : IJsonFormatter { public void Serialize(ref JsonWriter writer, IRankFeatureQuery value, IJsonFormatterResolver formatterResolver) @@ -206,6 +231,9 @@ public void Serialize(ref JsonWriter writer, IRankFeatureQuery value, IJsonForma case IRankFeatureLogarithmFunction log: SerializeScoreFunction(ref writer, "log", log, formatterResolver); break; + case IRankFeatureLinearFunction log: + SerializeScoreFunction(ref writer, "linear", log, formatterResolver); + break; } } @@ -232,7 +260,8 @@ private static IRankFeatureFunction DeserializeScoreFunction(ref { "field", 2 }, { "saturation", 3 }, { "log", 4 }, - { "sigmoid", 5 } + { "sigmoid", 5 }, + { "linear", 6 } }; public IRankFeatureQuery Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver) @@ -266,6 +295,9 @@ public IRankFeatureQuery Deserialize(ref JsonReader reader, IJsonFormatterResolv case 5: query.Function = DeserializeScoreFunction(ref reader, formatterResolver); break; + case 6: + query.Function = DeserializeScoreFunction(ref reader, formatterResolver); + break; } } else diff --git a/tests/Tests/QueryDsl/Specialized/RankFeature/RankFeatureQueryUsageTests.cs b/tests/Tests/QueryDsl/Specialized/RankFeature/RankFeatureQueryUsageTests.cs index 975924ac3b1..184f50b87d5 100644 --- a/tests/Tests/QueryDsl/Specialized/RankFeature/RankFeatureQueryUsageTests.cs +++ b/tests/Tests/QueryDsl/Specialized/RankFeature/RankFeatureQueryUsageTests.cs @@ -2,6 +2,7 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information +using Elastic.Elasticsearch.Xunit.XunitPlumbing; using Nest; using Tests.Core.ManagedElasticsearch.Clusters; using Tests.Domain; @@ -71,4 +72,27 @@ protected override QueryContainer QueryFluent(QueryContainerDescriptor .Field(f => f.Rank) ); } + + [SkipVersion("<7.12.0", "Introduced in 7.12.0")] + public class RankFeatureLinearFunctionUsageTests : QueryDslUsageTestsBase + { + public RankFeatureLinearFunctionUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } + protected override QueryContainer QueryInitializer => new RankFeatureQuery + { + Name = "named_query", + Boost = 1.1, + Field = Infer.Field(f => f.Rank), + Function = new RankFeatureLinearFunction() + }; + + protected override object QueryJson => + new { rank_feature = new { _name = "named_query", boost = 1.1, field = "rank", linear = new { } } }; + + protected override QueryContainer QueryFluent(QueryContainerDescriptor q) => q + .RankFeature(rf => rf + .Name("named_query") + .Boost(1.1) + .Field(f => f.Rank) + .Linear()); + } }