Skip to content

Commit bd83968

Browse files
committed
Add support for span multi term query.
Closes #863.
1 parent e89f847 commit bd83968

File tree

11 files changed

+158
-1
lines changed

11 files changed

+158
-1
lines changed

Diff for: src/Nest/DSL/Query/IQueryContainer.cs

+3
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ public interface IQueryContainer : ICustomJson
125125
[JsonProperty(PropertyName = "span_not")]
126126
ISpanNotQuery SpanNot { get; set; }
127127

128+
[JsonProperty(PropertyName = "span_multi")]
129+
ISpanMultiTermQuery SpanMultiTerm { get; set; }
130+
128131
[JsonProperty(PropertyName = "top_children")]
129132
ITopChildrenQuery TopChildren { get; set; }
130133

Diff for: src/Nest/DSL/Query/QueryContainer.cs

+2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ public class QueryContainer : IQueryContainer
7777

7878
ISpanNearQuery IQueryContainer.SpanNear { get; set; }
7979

80+
ISpanMultiTermQuery IQueryContainer.SpanMultiTerm { get; set; }
81+
8082
ITopChildrenQuery IQueryContainer.TopChildren { get; set; }
8183

8284
INestedQuery IQueryContainer.Nested { get; set; }

Diff for: src/Nest/DSL/Query/QueryDescriptor.cs

+13
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,19 @@ public QueryContainer SpanNot(Action<SpanNotQuery<T>> selector)
819819
return this.New(span, q => q.SpanNot = span);
820820
}
821821

822+
/// <summary>
823+
/// Wrap a multi term query (one of fuzzy, prefix, term range or regexp query)
824+
/// as a span query so it can be nested.
825+
/// </summary>
826+
public QueryContainer SpanMultiTerm(Action<SpanMultiTermQueryDescriptor<T>> selector)
827+
{
828+
selector.ThrowIfNull("selector");
829+
var span = new SpanMultiTermQueryDescriptor<T>();
830+
selector(span);
831+
832+
return this.New(span, q => q.SpanMultiTerm = span);
833+
}
834+
822835
/// <summary>
823836
/// custom_score query allows to wrap another query and customize the scoring of it optionally with a
824837
/// computation derived from other field values in the doc (numeric ones) using script or boost expression

Diff for: src/Nest/DSL/Query/SpanMultiTermQueryDescriptor.cs

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using Newtonsoft.Json;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
7+
namespace Nest
8+
{
9+
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
10+
public interface ISpanMultiTermQuery : ISpanSubQuery
11+
{
12+
[JsonProperty("match")]
13+
IQueryContainer Match { get; set; }
14+
}
15+
16+
public class SpanMultiTermQuery : PlainQuery, ISpanMultiTermQuery
17+
{
18+
protected override void WrapInContainer(IQueryContainer container)
19+
{
20+
container.SpanMultiTerm = this;
21+
}
22+
23+
public IQueryContainer Match { get; set; }
24+
25+
public bool IsConditionless { get { return false; } }
26+
}
27+
28+
public class SpanMultiTermQueryDescriptor<T> : ISpanMultiTermQuery
29+
where T : class
30+
{
31+
IQueryContainer ISpanMultiTermQuery.Match { get; set; }
32+
33+
bool IQuery.IsConditionless { get { return false; } }
34+
35+
public SpanMultiTermQueryDescriptor<T> Match(Func<QueryDescriptor<T>, QueryContainer> querySelector)
36+
{
37+
var q = new QueryDescriptor<T>();
38+
((ISpanMultiTermQuery)this).Match = querySelector(q);
39+
return this;
40+
}
41+
}
42+
}

Diff for: src/Nest/DSL/Query/SpanQueryDescriptor.cs

+14-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ public interface ISpanQuery : IQuery
2525

2626
[JsonProperty(PropertyName = "span_not")]
2727
ISpanNotQuery SpanNot { get; set; }
28+
29+
[JsonProperty(PropertyName = "span_multi")]
30+
ISpanMultiTermQuery SpanMultiTerm { get; set; }
2831
}
2932

3033
public class SpanQuery : ISpanQuery
@@ -35,6 +38,7 @@ public class SpanQuery : ISpanQuery
3538
public ISpanNearQuery SpanNear { get; set; }
3639
public ISpanOrQuery SpanOr { get; set; }
3740
public ISpanNotQuery SpanNot { get; set; }
41+
public ISpanMultiTermQuery SpanMultiTerm { get; set; }
3842
}
3943

4044
public class SpanQuery<T> : ISpanQuery where T : class
@@ -49,6 +53,8 @@ public class SpanQuery<T> : ISpanQuery where T : class
4953

5054
ISpanNotQuery ISpanQuery.SpanNot { get; set; }
5155

56+
ISpanMultiTermQuery ISpanQuery.SpanMultiTerm { get; set; }
57+
5258
bool IQuery.IsConditionless
5359
{
5460
get
@@ -59,7 +65,8 @@ bool IQuery.IsConditionless
5965
((ISpanQuery)this).SpanFirst as IQuery,
6066
((ISpanQuery)this).SpanNear as IQuery,
6167
((ISpanQuery)this).SpanOr as IQuery,
62-
((ISpanQuery)this).SpanNot as IQuery
68+
((ISpanQuery)this).SpanNot as IQuery,
69+
((ISpanQuery)this).SpanMultiTerm as IQuery
6370
};
6471
return queries.All(q => q == null || q.IsConditionless);
6572
}
@@ -117,6 +124,12 @@ public SpanQuery<T> SpanNot(Func<SpanNotQuery<T>, SpanNotQuery<T>> selector)
117124
var q = selector(new SpanNotQuery<T>());
118125
return CreateQuery(q, (sq) => ((ISpanQuery)sq).SpanNot = q);
119126
}
127+
public SpanQuery<T> SpanMultiTerm(Func<SpanMultiTermQueryDescriptor<T>, SpanMultiTermQueryDescriptor<T>> selector)
128+
{
129+
selector.ThrowIfNull("selector");
130+
var q= selector(new SpanMultiTermQueryDescriptor<T>());
131+
return CreateQuery(q, (sq) => ((ISpanQuery)sq).SpanMultiTerm = q);
132+
}
120133

121134
private SpanQuery<T> CreateQuery<K>(K query, Action<SpanQuery<T>> setProperty) where K : ISpanSubQuery
122135
{

Diff for: src/Nest/Domain/DSL/Query.cs

+5
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,11 @@ public static QueryContainer SpanTerm(string field, string value, double? Boost
205205
return new QueryDescriptor<T>().SpanTerm(field, value, Boost);
206206
}
207207

208+
public static QueryContainer SpanMultiTerm(Action<SpanMultiTermQueryDescriptor<T>> selector)
209+
{
210+
return new QueryDescriptor<T>().SpanMultiTerm(selector);
211+
}
212+
208213
public static QueryContainer Term<K>(Expression<Func<T, K>> fieldDescriptor, K value, double? Boost = null)
209214
{
210215
return new QueryDescriptor<T>().Term(fieldDescriptor, value, Boost);

Diff for: src/Nest/Nest.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@
170170
<Compile Include="DSL\MultiPercolateDescriptor.cs" />
171171
<Compile Include="DSL\Paths\IndexOptionalNamePathDescriptor.cs" />
172172
<Compile Include="DSL\Paths\IndicesOptionalTypesNamePathDecriptor.cs" />
173+
<Compile Include="DSL\Query\SpanMultiTermQueryDescriptor.cs" />
173174
<Compile Include="DSL\TypeExistsDescriptor.cs" />
174175
<Compile Include="DSL\Query\Functions\FieldValueFactorDescriptor.cs" />
175176
<Compile Include="DSL\Query\GeoShapeMultiPointQueryDescriptor.cs" />

Diff for: src/Tests/Nest.Tests.Integration/Nest.Tests.Integration.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@
172172
<Compile Include="Search\Filter\PrefixFilterTests.cs" />
173173
<Compile Include="Search\Filter\RangeFilterTests.cs" />
174174
<Compile Include="Search\Query\BoolQueryResults.cs" />
175+
<Compile Include="Search\Query\SpanQueryTests.cs" />
175176
<Compile Include="Search\Query\TermToString.cs" />
176177
<Compile Include="Core\UpdateTests.cs" />
177178
<Compile Include="Search\Filter\BoolFilterTests.cs" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using FluentAssertions;
2+
using Nest.Tests.MockData.Domain;
3+
using NUnit.Framework;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
10+
namespace Nest.Tests.Integration.Search.Query
11+
{
12+
[TestFixture]
13+
public class SpanQueryTests : IntegrationTests
14+
{
15+
[Test]
16+
public void SpanMultiTermQuery()
17+
{
18+
var r = Client.Search<ElasticsearchProject>(s => s
19+
.Query(q => q
20+
.SpanMultiTerm(sp => sp
21+
.Match(m => m
22+
.Prefix(p => p
23+
.OnField(ep => ep.Name)
24+
.Value("NEST")
25+
)
26+
)
27+
)
28+
)
29+
);
30+
31+
r.IsValid.Should().BeTrue();
32+
}
33+
}
34+
}

Diff for: src/Tests/Nest.Tests.Unit/Nest.Tests.Unit.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@
398398
<Compile Include="Search\Query\Singles\HasParentQueryJson.cs" />
399399
<Compile Include="Search\Query\Singles\MultiMatch\MultiMatchJson.cs" />
400400
<Compile Include="Search\Query\Modes\QueryModesTests.cs" />
401+
<Compile Include="Search\Query\Singles\SpanMultiTermQueryJson.cs" />
401402
<Compile Include="Search\Query\Singles\Term\TermToStringJson.cs" />
402403
<Compile Include="Search\Rescoring\RescoreTests.cs" />
403404
<Compile Include="Search\Facets\DateHistogramFacetJson.cs" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using Nest.Tests.MockData.Domain;
2+
using NUnit.Framework;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
9+
namespace Nest.Tests.Unit.Search.Query.Singles
10+
{
11+
[TestFixture]
12+
public class SpanMultiTermQueryJson : BaseJsonTests
13+
{
14+
[Test]
15+
public void SpanMultiTermQuery()
16+
{
17+
var s = new SearchDescriptor<ElasticsearchProject>()
18+
.From(0)
19+
.Size(10)
20+
.Query(q => q
21+
.SpanMultiTerm(sp => sp
22+
.Match(m => m
23+
.Prefix(p => p
24+
.OnField(ep => ep.Name)
25+
.Value("NEST")
26+
)
27+
)
28+
)
29+
);
30+
var json = TestElasticClient.Serialize(s);
31+
var expected = @"{ from: 0, size: 10, query :
32+
{
33+
span_multi:{
34+
match:{
35+
prefix : { name : { value : ""NEST"" } }
36+
}
37+
}
38+
}}";
39+
Assert.True(json.JsonEquals(expected), json);
40+
}
41+
}
42+
}

0 commit comments

Comments
 (0)