Skip to content

Add rank_feature, rank_feature fields and rank_feature query #3941

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 6 commits into from
Jul 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/code-standards/descriptors.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ var methods = from d in YieldAllDescriptors()
where !(m.Name == nameof(RuleConditionDescriptor.AppliesTo) && dt == typeof(RuleConditionDescriptor))
where !(m.Name == nameof(RuleConditionDescriptor.Operator) && dt == typeof(RuleConditionDescriptor))
where !(m.Name == nameof(RuleConditionDescriptor.Value) && dt == typeof(RuleConditionDescriptor))
where !(m.Name == nameof(RankFeatureLogarithmFunctionDescriptor.ScalingFactor) && dt == typeof(RankFeatureLogarithmFunctionDescriptor))
where !(m.Name == nameof(RankFeatureSigmoidFunctionDescriptor.Exponent) && dt == typeof(RankFeatureSigmoidFunctionDescriptor))
where !(m.Name == nameof(RankFeatureSigmoidFunctionDescriptor.Pivot) && dt == typeof(RankFeatureSigmoidFunctionDescriptor))

select new {m, d, p};

Expand Down
4 changes: 4 additions & 0 deletions docs/query-dsl.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,8 @@ Specialized types of queries that do not fit into other groups

* <<percolate-query-usage,Percolate Query Usage>>

* <<rank-feature-query-usage,Rank Feature Query Usage>>

* <<script-query-usage,Script Query Usage>>

* <<script-score-query-usage,Script Score Query Usage>>
Expand All @@ -287,6 +289,8 @@ include::query-dsl/specialized/more-like-this/more-like-this-query-usage.asciido

include::query-dsl/specialized/percolate/percolate-query-usage.asciidoc[]

include::query-dsl/specialized/rank-feature/rank-feature-query-usage.asciidoc[]

include::query-dsl/specialized/script/script-query-usage.asciidoc[]

include::query-dsl/specialized/script-score/script-score-query-usage.asciidoc[]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/7.0

:github: https://github.com/elastic/elasticsearch-net

:nuget: https://www.nuget.org/packages

////
IMPORTANT NOTE
==============
This file has been generated from https://github.com/elastic/elasticsearch-net/tree/master/src/Tests/Tests/QueryDsl/Specialized/RankFeature/RankFeatureQueryUsageTests.cs.
If you wish to submit a PR for any spelling mistakes, typos or grammatical errors for this file,
please modify the original csharp file found at the link and submit the PR with that change. Thanks!
////

[[rank-feature-query-usage]]
=== Rank Feature Query Usage

The rank_feature query is a specialized query that only works on `rank_feature` fields and `rank_features` fields.
Its goal is to boost the score of documents based on the values of numeric features. It is typically put in a should clause of a bool query
so that its score is added to the score of the query.

Compared to using `function_score` or other ways to modify the score, this query has the benefit of being able to efficiently
skip non-competitive hits when track_total_hits is not set to true. Speedups may be spectacular.

See the Elasticsearch documentation on {ref_current}/query-dsl-rank-feature-query.html[rank feature query] for more details.

==== Fluent DSL example

[source,csharp]
----
q
.RankFeature(rf => rf
.Name("named_query")
.Boost(1.1)
.Field(f => f.Rank)
.Saturation()
)
----

==== Object Initializer syntax example

[source,csharp]
----
new RankFeatureQuery()
{
Name = "named_query",
Boost = 1.1,
Field = Infer.Field<Project>(f => f.Rank),
Function = new RankFeatureSaturationFunction()
}
----

[source,javascript]
.Example json output
----
{
"rank_feature": {
"_name": "named_query",
"boost": 1.1,
"field": "rank",
"saturation": {}
}
}
----

19 changes: 19 additions & 0 deletions src/Nest/Mapping/Types/Core/RankFeature/RankFeatureAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Nest
{
/// <inheritdoc cref="IRankFeatureProperty"/>
public class RankFeatureAttribute : ElasticsearchPropertyAttributeBase, IRankFeatureProperty
{
public RankFeatureAttribute() : base(FieldType.RankFeature) { }

private IRankFeatureProperty Self => this;

/// <inheritdoc cref="IRankFeatureProperty.PositiveScoreImpact"/>
public bool PositiveScoreImpact
{
get => Self.PositiveScoreImpact.GetValueOrDefault(true);
set => Self.PositiveScoreImpact = value;
}

bool? IRankFeatureProperty.PositiveScoreImpact { get; set; }
}
}
48 changes: 48 additions & 0 deletions src/Nest/Mapping/Types/Core/RankFeature/RankFeatureProperty.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Diagnostics;
using System.Runtime.Serialization;
using Elasticsearch.Net.Utf8Json;

namespace Nest
{
/// <summary>
/// A field that can index numbers so that they can later be used
/// to boost documents in queries with a rank_feature query.
/// </summary>
[InterfaceDataContract]
public interface IRankFeatureProperty : IProperty
{
/// <summary>
/// Rank features that correlate negatively with the score should set <see cref="PositiveScoreImpact"/>
/// to false (defaults to true). This will be used by the rank_feature query to modify the scoring
/// formula in such a way that the score decreases with the value of the feature instead of
/// increasing. For instance in web search, the url length is a commonly used feature
/// which correlates negatively with scores.
/// </summary>
[DataMember(Name = "positive_score_impact")]
bool? PositiveScoreImpact { get; set; }
}

/// <inheritdoc cref="IRankFeatureProperty" />
public class RankFeatureProperty : PropertyBase, IRankFeatureProperty
{
public RankFeatureProperty() : base(FieldType.RankFeature) { }

/// <inheritdoc />
public bool? PositiveScoreImpact { get; set; }
}

/// <inheritdoc cref="IRankFeatureProperty" />
[DebuggerDisplay("{DebugDisplay}")]
public class RankFeaturePropertyDescriptor<T>
: PropertyDescriptorBase<RankFeaturePropertyDescriptor<T>, IRankFeatureProperty, T>, IRankFeatureProperty
where T : class
{
public RankFeaturePropertyDescriptor() : base(FieldType.RankFeature) { }

bool? IRankFeatureProperty.PositiveScoreImpact { get; set; }

/// <inheritdoc cref="IRankFeatureProperty.PositiveScoreImpact" />
public RankFeaturePropertyDescriptor<T> PositiveScoreImpact(bool? positiveScoreImpact = true) =>
Assign(positiveScoreImpact, (a, v) => a.PositiveScoreImpact = v);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Nest
{
/// <inheritdoc cref="IRankFeaturesProperty"/>
public class RankFeaturesAttribute : ElasticsearchPropertyAttributeBase, IRankFeaturesProperty
{
public RankFeaturesAttribute() : base(FieldType.RankFeatures) { }
}
}
31 changes: 31 additions & 0 deletions src/Nest/Mapping/Types/Core/RankFeatures/RankFeaturesProperty.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Diagnostics;
using System.Runtime.Serialization;
using Elasticsearch.Net.Utf8Json;

namespace Nest
{
/// <summary>
/// A field that can index numeric feature vectors, so that they can later be used to boost documents in queries with a rank_feature query.
/// It is analogous to the <see cref="IRankFeatureProperty"/> datatype, but is better suited when the list of features is sparse so that it
/// wouldn't be reasonable to add one field to the mappings for each of them.
/// </summary>
[InterfaceDataContract]
public interface IRankFeaturesProperty : IProperty
{
}

/// <inheritdoc cref="IRankFeaturesProperty" />
public class RankFeaturesProperty : PropertyBase, IRankFeaturesProperty
{
public RankFeaturesProperty() : base(FieldType.RankFeatures) { }
}

/// <inheritdoc cref="IRankFeaturesProperty" />
[DebuggerDisplay("{DebugDisplay}")]
public class RankFeaturesPropertyDescriptor<T>
: PropertyDescriptorBase<RankFeaturesPropertyDescriptor<T>, IRankFeaturesProperty, T>, IRankFeaturesProperty
where T : class
{
public RankFeaturesPropertyDescriptor() : base(FieldType.RankFeatures) { }
}
}
6 changes: 6 additions & 0 deletions src/Nest/Mapping/Types/FieldType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,5 +118,11 @@ public enum FieldType

[EnumMember(Value = "join")]
Join,

[EnumMember(Value = "rank_feature")]
RankFeature,

[EnumMember(Value = "rank_features")]
RankFeatures
}
}
6 changes: 6 additions & 0 deletions src/Nest/Mapping/Types/Properties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,12 @@ public PropertiesDescriptor<T> Object<TChild>(Func<ObjectTypeDescriptor<T, TChil

public PropertiesDescriptor<T> FieldAlias(Func<FieldAliasPropertyDescriptor<T>, IFieldAliasProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IRankFeatureProperty"/>
public PropertiesDescriptor<T> RankFeature(Func<RankFeaturePropertyDescriptor<T>, IRankFeatureProperty> selector) => SetProperty(selector);

/// <inheritdoc cref="IRankFeaturesProperty"/>
public PropertiesDescriptor<T> RankFeatures(Func<RankFeaturesPropertyDescriptor<T>, IRankFeaturesProperty> selector) => SetProperty(selector);

public PropertiesDescriptor<T> Custom(IProperty customType) => SetProperty(customType);

private PropertiesDescriptor<T> SetProperty<TDescriptor, TInterface>(Func<TDescriptor, TInterface> selector)
Expand Down
2 changes: 1 addition & 1 deletion src/Nest/Mapping/Types/PropertyBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public interface IProperty : IFieldMapping
/// <summary>
/// The name of the property
/// </summary>
//[DataMember(Name = "name")]
[IgnoreDataMember]
PropertyName Name { get; set; }

/// <summary>
Expand Down
8 changes: 8 additions & 0 deletions src/Nest/Mapping/Types/PropertyFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ public IProperty Deserialize(ref JsonReader reader, IJsonFormatterResolver forma
case FieldType.IpRange: return Deserialize<IpRangeProperty>(ref segmentReader, formatterResolver);
case FieldType.Join: return Deserialize<JoinProperty>(ref segmentReader, formatterResolver);
case FieldType.Alias: return Deserialize<FieldAliasProperty>(ref segmentReader, formatterResolver);
case FieldType.RankFeature: return Deserialize<RankFeatureProperty>(ref segmentReader, formatterResolver);
case FieldType.RankFeatures: return Deserialize<RankFeaturesProperty>(ref segmentReader, formatterResolver);
case FieldType.None:
// no "type" field in the property mapping
return Deserialize<ObjectProperty>(ref segmentReader, formatterResolver);
Expand Down Expand Up @@ -181,6 +183,12 @@ public void Serialize(ref JsonWriter writer, IProperty value, IJsonFormatterReso
case "alias":
Serialize<IFieldAliasProperty>(ref writer, value, formatterResolver);
break;
case "rank_feature":
Serialize<IRankFeatureProperty>(ref writer, value, formatterResolver);
break;
case "rank_features":
Serialize<IRankFeaturesProperty>(ref writer, value, formatterResolver);
break;
default:
if (value is IGenericProperty genericProperty)
Serialize<IGenericProperty>(ref writer, genericProperty, formatterResolver);
Expand Down
8 changes: 8 additions & 0 deletions src/Nest/Mapping/Visitor/IMappingVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ public interface IMappingVisitor
void Visit(IIpRangeProperty property);

void Visit(IJoinProperty property);

void Visit(IRankFeatureProperty property);

void Visit(IRankFeaturesProperty property);
}

public class NoopMappingVisitor : IMappingVisitor
Expand Down Expand Up @@ -100,5 +104,9 @@ public virtual void Visit(IDateRangeProperty property) { }
public virtual void Visit(IIpRangeProperty property) { }

public virtual void Visit(IJoinProperty property) { }

public virtual void Visit(IRankFeatureProperty property) { }

public virtual void Visit(IRankFeaturesProperty property) { }
}
}
4 changes: 4 additions & 0 deletions src/Nest/Mapping/Visitor/IPropertyVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ public interface IPropertyVisitor

void Visit(IJoinProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute);

void Visit(IRankFeatureProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute);

void Visit(IRankFeaturesProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute);

void Visit(IProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute);

IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute);
Expand Down
12 changes: 12 additions & 0 deletions src/Nest/Mapping/Visitor/MappingWalker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,18 @@ public void Accept(IProperties properties)
case FieldType.Join:
Visit<IJoinProperty>(field, t => { _visitor.Visit(t); });
break;
case FieldType.RankFeature:
Visit<IRankFeatureProperty>(field, t =>
{
_visitor.Visit(t);
});
break;
case FieldType.RankFeatures:
Visit<IRankFeaturesProperty>(field, t =>
{
_visitor.Visit(t);
});
break;
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/Nest/Mapping/Visitor/NoopPropertyVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ public void Visit(IIpRangeProperty type, PropertyInfo propertyInfo, Elasticsearc

public void Visit(IJoinProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) { }

public virtual void Visit(IRankFeatureProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) { }

public virtual void Visit(IRankFeaturesProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) { }

public virtual void Visit(IIpProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) { }

public virtual void Visit(IGeoPointProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute) { }
Expand Down Expand Up @@ -122,6 +126,12 @@ public void Visit(IProperty type, PropertyInfo propertyInfo, ElasticsearchProper
case IIpRangeProperty ipRangeType:
Visit(ipRangeType, propertyInfo, attribute);
break;
case IRankFeatureProperty rankFeature:
Visit(rankFeature, propertyInfo, attribute);
break;
case IRankFeaturesProperty rankFeatures:
Visit(rankFeatures, propertyInfo, attribute);
break;
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/Nest/QueryDsl/Abstractions/Container/IQueryContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ public interface IQueryContainer
[DataMember(Name = "wildcard")]
IWildcardQuery Wildcard { get; set; }

/// <inheritdoc cref="IRankFeatureQuery"/>
[DataMember(Name = "rank_feature")]
IRankFeatureQuery RankFeature { get; set; }

void Accept(IQueryVisitor visitor);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public partial class QueryContainer : IQueryContainer, IDescriptor
private ITermsQuery _terms;
private ITermsSetQuery _termsSet;
private IWildcardQuery _wildcard;
private IRankFeatureQuery _rankFeature;

[IgnoreDataMember]
private IQueryContainer Self => this;
Expand Down Expand Up @@ -342,6 +343,12 @@ IWildcardQuery IQueryContainer.Wildcard
set => _wildcard = Set(value);
}

IRankFeatureQuery IQueryContainer.RankFeature
{
get => _rankFeature;
set => _rankFeature = Set(value);
}

private T Set<T>(T value) where T : IQuery
{
if (ContainedQuery != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,10 @@ public QueryContainer Ids(Func<IdsQueryDescriptor, IIdsQuery> selector) =>
public QueryContainer Intervals(Func<IntervalsQueryDescriptor<T>, IIntervalsQuery> selector) =>
WrapInContainer(selector, (query, container) => container.Intervals = query);

/// <inheritdoc cref="IRankFeatureQuery"/>
public QueryContainer RankFeature(Func<RankFeatureQueryDescriptor<T>, IRankFeatureQuery> selector) =>
WrapInContainer(selector, (query, container) => container.RankFeature = query);

/// <summary>
/// Matches spans containing a term. The span term query maps to Lucene SpanTermQuery.
/// </summary>
Expand Down
4 changes: 4 additions & 0 deletions src/Nest/QueryDsl/Query.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ public static QueryContainer LongRange(Func<LongRangeQueryDescriptor<T>, ILongRa
public static QueryContainer Regexp(Func<RegexpQueryDescriptor<T>, IRegexpQuery> selector) =>
new QueryContainerDescriptor<T>().Regexp(selector);

/// <inheritdoc cref="IRankFeatureQuery"/>
public static QueryContainer RankFeature(Func<RankFeatureQueryDescriptor<T>, IRankFeatureQuery> selector) =>
new QueryContainerDescriptor<T>().RankFeature(selector);

public static QueryContainer Script(Func<ScriptQueryDescriptor<T>, IScriptQuery> selector) =>
new QueryContainerDescriptor<T>().Script(selector);

Expand Down
Loading