Skip to content

Commit ec4fe7b

Browse files
committed
Merge branch 'function_score' of github.com:andreabalducci/NEST
Conflicts: src/Nest.Tests.Unit/Nest.Tests.Unit.csproj src/Nest/DSL/Query.cs src/Nest/DSL/QueryDescriptor.cs src/Nest/Nest.csproj
2 parents 33fbab5 + cc4f832 commit ec4fe7b

File tree

6 files changed

+313
-2
lines changed

6 files changed

+313
-2
lines changed

src/Nest.Tests.Unit/Nest.Tests.Unit.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@
112112
<Compile Include="Search\Filter\BoolFilterMerges\BoolFilterMergesTests.cs" />
113113
<Compile Include="Search\Filter\Singles\HasParentFilterJson.cs" />
114114
<Compile Include="Search\Query\Singles\RegexpQueryJson.cs" />
115+
<Compile Include="Search\Query\Singles\FunctionScoreQueryJson.cs" />
115116
<Compile Include="Search\Query\Singles\HasParentQueryJson.cs" />
116117
<Compile Include="Search\Query\Singles\MultiMatch\MultiMatchJson.cs" />
117118
<Compile Include="Search\Query\Singles\Term\TermToStringJson.cs" />
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using NUnit.Framework;
2+
using Nest.DSL.Query;
3+
using Nest.Tests.MockData.Domain;
4+
5+
namespace Nest.Tests.Unit.Search.Query.Singles
6+
{
7+
[TestFixture]
8+
public class FunctionScoreQueryTests
9+
{
10+
[Test]
11+
public void FunctionScoreQuery()
12+
{
13+
var s = new SearchDescriptor<ElasticSearchProject>().From(0).Size(10)
14+
.Query(q => q
15+
.FunctionScore(fs => fs
16+
.Query(qq => qq.MatchAll())
17+
.Functions(
18+
f => f.Gauss(x=>x.StartedOn, d=>d.Scale("42w")),
19+
f => f.Linear(x => x.FloatValue, d => d.Scale("0.3")),
20+
f => f.Exp(x => x.DoubleValue, d => d.Scale("0.5")),
21+
f => f.BoostFactor(2)
22+
)
23+
.ScoreMode(FunctionScoreMode.sum)
24+
)
25+
).Fields(x=>x.Content);
26+
27+
var json = TestElasticClient.Serialize(s);
28+
var expected = @"{
29+
from: 0, size: 10,
30+
query : {
31+
function_score : {
32+
functions: [
33+
{gauss: { startedOn : { scale: '42w'}}},
34+
{linear: { floatValue : { scale: '0.3'}}},
35+
{exp: { doubleValue: { scale: '0.5'}}},
36+
{boost_factor: 2.0 }
37+
],
38+
query : { match_all : {} },
39+
score_mode: 'sum'
40+
}
41+
},
42+
fields: [""content""]
43+
}";
44+
Assert.True(json.JsonEquals(expected), json);
45+
}
46+
}
47+
}

src/Nest/DSL/Query.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Linq;
44
using System.Text;
5+
using Nest.DSL.Query;
56
using Newtonsoft.Json;
67
using Newtonsoft.Json.Converters;
78
using Nest.Resolvers.Converters;
@@ -238,10 +239,13 @@ public static BaseQuery Wildcard(string field, string value, double? Boost = nul
238239
return new QueryDescriptor<T>().Wildcard(field, value, Boost);
239240
}
240241

241-
public static BaseQuery Regexp(Action<RegexpQueryDescriptor<T>> regexpSelector)
242+
public static BaseQuery FunctionScore(Action<FunctionScoreQueryDescriptor<T>> functionScoreQuery)
243+
{
244+
return new QueryDescriptor<T>().FunctionScore(functionScoreQuery);
245+
}
246+
public static BaseQuery Regexp(Action<RegexpQueryDescriptor<T>> regexpSelector)
242247
{
243248
return new QueryDescriptor<T>().Regexp(regexpSelector);
244249
}
245-
246250
}
247251
}
Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Linq.Expressions;
6+
using System.Text;
7+
using Nest.Resolvers;
8+
using Newtonsoft.Json;
9+
using Newtonsoft.Json.Converters;
10+
11+
namespace Nest.DSL.Query
12+
{
13+
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
14+
public class FunctionScoreQueryDescriptor<T> : IQuery where T : class
15+
{
16+
[JsonProperty(PropertyName = "functions")]
17+
internal IEnumerable<FunctionScoreFunction<T>> _Functions { get; set; }
18+
19+
[JsonProperty(PropertyName = "query")]
20+
internal BaseQuery _Query { get; set; }
21+
22+
[JsonProperty(PropertyName = "score_mode")]
23+
[JsonConverter(typeof(StringEnumConverter))]
24+
FunctionScoreMode _ScoreMode { get; set; }
25+
26+
27+
internal bool IsConditionless
28+
{
29+
get
30+
{
31+
return this._Query == null || this._Query.IsConditionless;
32+
}
33+
}
34+
35+
public FunctionScoreQueryDescriptor<T> Query(Func<QueryDescriptor<T>, BaseQuery> querySelector)
36+
{
37+
querySelector.ThrowIfNull("querySelector");
38+
var query = new QueryDescriptor<T>();
39+
var q = querySelector(query);
40+
41+
this._Query = q;
42+
return this;
43+
}
44+
45+
public FunctionScoreQueryDescriptor<T> Functions(params Func<FunctionScoreFunctionsDescriptor<T>, FunctionScoreFunction<T>>[] functions)
46+
{
47+
var descriptor = new FunctionScoreFunctionsDescriptor<T>();
48+
49+
foreach (var f in functions)
50+
{
51+
f(descriptor);
52+
}
53+
54+
_Functions = descriptor;
55+
56+
return this;
57+
}
58+
59+
public FunctionScoreQueryDescriptor<T> ScoreMode(FunctionScoreMode mode)
60+
{
61+
this._ScoreMode = mode;
62+
return this;
63+
}
64+
}
65+
66+
public enum FunctionScoreMode
67+
{
68+
multiply,
69+
sum,
70+
avg,
71+
first,
72+
max,
73+
min
74+
}
75+
76+
public class FunctionScoreFunctionsDescriptor<T> : IEnumerable<FunctionScoreFunction<T>>
77+
{
78+
internal List<FunctionScoreFunction<T>> _Functions { get; set; }
79+
80+
public FunctionScoreFunctionsDescriptor()
81+
{
82+
this._Functions = new List<FunctionScoreFunction<T>>();
83+
}
84+
85+
public FunctionScoreFunction<T> Gauss(Expression<Func<T, object>> objectPath, Action<FunctionScoreDecayFieldDescriptor> db)
86+
{
87+
var fn = new GaussFunction<T>(objectPath, db);
88+
this._Functions.Add(fn);
89+
return fn;
90+
}
91+
92+
public FunctionScoreFunction<T> Linear(Expression<Func<T, object>> objectPath, Action<FunctionScoreDecayFieldDescriptor> db)
93+
{
94+
var fn = new LinearFunction<T>(objectPath, db);
95+
this._Functions.Add(fn);
96+
return fn;
97+
}
98+
99+
public FunctionScoreFunction<T> Exp(Expression<Func<T, object>> objectPath, Action<FunctionScoreDecayFieldDescriptor> db)
100+
{
101+
var fn = new ExpFunction<T>(objectPath, db);
102+
this._Functions.Add(fn);
103+
return fn;
104+
}
105+
106+
public BoostFactorFunction<T> BoostFactor(double value)
107+
{
108+
var fn = new BoostFactorFunction<T>(value);
109+
this._Functions.Add(fn);
110+
return fn;
111+
}
112+
113+
114+
public IEnumerator<FunctionScoreFunction<T>> GetEnumerator()
115+
{
116+
return _Functions.GetEnumerator();
117+
}
118+
119+
IEnumerator IEnumerable.GetEnumerator()
120+
{
121+
return _Functions.GetEnumerator();
122+
}
123+
}
124+
125+
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
126+
public class FunctionScoreFunction<T>
127+
{
128+
}
129+
130+
public class FunctionScoreDecayFieldDescriptor
131+
{
132+
[JsonProperty(PropertyName = "origin")]
133+
internal string _Origin { get; set; }
134+
135+
[JsonProperty(PropertyName = "scale")]
136+
internal string _Scale { get; set; }
137+
138+
[JsonProperty(PropertyName = "offset")]
139+
internal string _Offset { get; set; }
140+
141+
[JsonProperty(PropertyName = "decay")]
142+
internal double? _Decay { get; set; }
143+
144+
public FunctionScoreDecayFieldDescriptor Origin(string origin)
145+
{
146+
this._Origin = origin;
147+
return this;
148+
}
149+
150+
public FunctionScoreDecayFieldDescriptor Scale(string scale)
151+
{
152+
this._Scale = scale;
153+
return this;
154+
}
155+
156+
public FunctionScoreDecayFieldDescriptor Offset(string offset)
157+
{
158+
this._Offset = offset;
159+
return this;
160+
}
161+
162+
public FunctionScoreDecayFieldDescriptor Decay(double? decay)
163+
{
164+
this._Decay = decay;
165+
return this;
166+
}
167+
}
168+
169+
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
170+
public class FunctionScoreDecayFunction<T> : FunctionScoreFunction<T>
171+
{
172+
}
173+
174+
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
175+
public class GaussFunction<T> : FunctionScoreDecayFunction<T>
176+
{
177+
[JsonProperty(PropertyName = "gauss")]
178+
[JsonConverter(typeof(DictionaryKeysAreNotPropertyNamesJsonConverter))]
179+
internal IDictionary<string, FunctionScoreDecayFieldDescriptor> _GaussDescriptor { get; set; }
180+
181+
public GaussFunction(Expression<Func<T, object>> objectPath, Action<FunctionScoreDecayFieldDescriptor> descriptorBuilder)
182+
{
183+
_GaussDescriptor = new Dictionary<string, FunctionScoreDecayFieldDescriptor>();
184+
185+
var resolver = new PropertyNameResolver();
186+
var fieldName = resolver.Resolve(objectPath);
187+
var descriptor = new FunctionScoreDecayFieldDescriptor();
188+
descriptorBuilder(descriptor);
189+
_GaussDescriptor[fieldName] = descriptor;
190+
}
191+
}
192+
193+
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
194+
public class LinearFunction<T> : FunctionScoreDecayFunction<T>
195+
{
196+
[JsonProperty(PropertyName = "linear")]
197+
[JsonConverter(typeof(DictionaryKeysAreNotPropertyNamesJsonConverter))]
198+
internal IDictionary<string, FunctionScoreDecayFieldDescriptor> _LinearDescriptor { get; set; }
199+
200+
public LinearFunction(Expression<Func<T, object>> objectPath, Action<FunctionScoreDecayFieldDescriptor> descriptorBuilder)
201+
{
202+
_LinearDescriptor = new Dictionary<string, FunctionScoreDecayFieldDescriptor>();
203+
204+
var resolver = new PropertyNameResolver();
205+
var fieldName = resolver.Resolve(objectPath);
206+
var descriptor = new FunctionScoreDecayFieldDescriptor();
207+
descriptorBuilder(descriptor);
208+
_LinearDescriptor[fieldName] = descriptor;
209+
}
210+
}
211+
212+
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
213+
public class ExpFunction<T> : FunctionScoreDecayFunction<T>
214+
{
215+
[JsonProperty(PropertyName = "exp")]
216+
[JsonConverter(typeof(DictionaryKeysAreNotPropertyNamesJsonConverter))]
217+
internal IDictionary<string, FunctionScoreDecayFieldDescriptor> _ExpDescriptor { get; set; }
218+
219+
public ExpFunction(Expression<Func<T, object>> objectPath, Action<FunctionScoreDecayFieldDescriptor> descriptorBuilder)
220+
{
221+
_ExpDescriptor = new Dictionary<string, FunctionScoreDecayFieldDescriptor>();
222+
223+
var resolver = new PropertyNameResolver();
224+
var fieldName = resolver.Resolve(objectPath);
225+
var descriptor = new FunctionScoreDecayFieldDescriptor();
226+
descriptorBuilder(descriptor);
227+
_ExpDescriptor[fieldName] = descriptor;
228+
}
229+
}
230+
231+
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
232+
public class BoostFactorFunction<T> : FunctionScoreFunction<T>
233+
{
234+
[JsonProperty(PropertyName = "boost_factor")]
235+
internal double _BoostFactor { get; set; }
236+
237+
public BoostFactorFunction(double boostFactor)
238+
{
239+
_BoostFactor = boostFactor;
240+
}
241+
}
242+
}

src/Nest/DSL/QueryDescriptor.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,5 +896,21 @@ public BaseQuery Regexp(Action<RegexpQueryDescriptor<T>> regexpSelector)
896896
};
897897
return this.New(q => q.RegexpQueryDescriptor = regexp);
898898
}
899+
900+
/// <summary>
901+
/// Function score query
902+
/// </summary>
903+
/// <returns></returns>
904+
public BaseQuery FunctionScore(Action<FunctionScoreQueryDescriptor<T>> functionScoreQuery)
905+
{
906+
var query = new FunctionScoreQueryDescriptor<T>();
907+
functionScoreQuery(query);
908+
909+
if (query.IsConditionless)
910+
return CreateConditionlessQueryDescriptor(query);
911+
912+
this.FunctionScoreQueryDescriptor = query;
913+
return new QueryDescriptor<T> { FunctionScoreQueryDescriptor = this.FunctionScoreQueryDescriptor };
914+
}
899915
}
900916
}

src/Nest/Nest.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
<Compile Include="Enums\DynamicMappingOption.cs" />
7979
<Compile Include="Enums\Enums.Generated.cs" />
8080
<Compile Include="DSL\Suggest\CompletionSuggestDescriptor.cs" />
81+
<Compile Include="DSL\Query\FunctionScoreQueryDescriptor.cs" />
8182
<Compile Include="ExposedInternals\ElasticInferrer.cs" />
8283
<Compile Include="ExposedInternals\ElasticSerializer.cs" />
8384
<Compile Include="Exception\ConnectionException.cs" />

0 commit comments

Comments
 (0)