Skip to content

Commit ef0a8bb

Browse files
committed
Add support for per_field_analyzer on MLT and Termvector
Closes #1109
1 parent 6a74667 commit ef0a8bb

File tree

5 files changed

+89
-7
lines changed

5 files changed

+89
-7
lines changed

src/Nest/DSL/MultiGet/IMultiGetOperation.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,14 @@ public interface IMultiGetOperation
3030
// MoreLikeThisQuery and have a dedicatd MoreLikeThisDocument object.
3131
[JsonProperty(PropertyName = "doc")]
3232
object Document { get; set; }
33-
33+
34+
// Only used for the MLT query for providing a different analyzer per
35+
// artificial document field.
36+
// TODO: For 2.0, we should consider decoupling IMultiGetOperation from
37+
// MoreLikeThisQuery and have a dedicatd MoreLikeThisDocument object.
38+
[JsonProperty(PropertyName = "per_field_analyzer")]
39+
IDictionary<PropertyPathMarker, string> PerFieldAnalyzer { get; set; }
40+
3441
Type ClrType { get; }
3542
}
3643
}

src/Nest/DSL/MultiGet/MultiGetOperationDescriptor.cs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ public MultiGetOperation(long id) : this(id.ToString(CultureInfo.InvariantCultur
3333
public string Routing { get; set; }
3434

3535
public object Document { get; set; }
36+
37+
public IDictionary<PropertyPathMarker, string> PerFieldAnalyzer { get; set; }
3638
}
3739

3840
public class MultiGetOperationDescriptor<T> : IMultiGetOperation
@@ -47,6 +49,7 @@ public class MultiGetOperationDescriptor<T> : IMultiGetOperation
4749
ISourceFilter IMultiGetOperation.Source { get; set; }
4850
IList<PropertyPathMarker> IMultiGetOperation.Fields { get; set; }
4951
object IMultiGetOperation.Document { get; set; }
52+
IDictionary<PropertyPathMarker, string> IMultiGetOperation.PerFieldAnalyzer { get; set; }
5053
Type IMultiGetOperation.ClrType { get { return typeof(T); } }
5154

5255
public MultiGetOperationDescriptor()
@@ -63,7 +66,8 @@ public MultiGetOperationDescriptor()
6366
/// </pre>
6467
/// </summary>
6568
/// <param name="initializeEmpty"></param>
66-
public MultiGetOperationDescriptor(bool allowExplicitIndex) : this()
69+
public MultiGetOperationDescriptor(bool allowExplicitIndex)
70+
: this()
6771
{
6872
if (allowExplicitIndex) return;
6973
Self.Index = null;
@@ -89,7 +93,7 @@ public MultiGetOperationDescriptor<T> Type(string type)
8993
return this;
9094
}
9195

92-
96+
9397
/// <summary>
9498
/// Manually set the type of which a typename will be inferred
9599
/// </summary>
@@ -144,7 +148,7 @@ public MultiGetOperationDescriptor<T> Routing(string routing)
144148
/// </summary>
145149
public MultiGetOperationDescriptor<T> Fields(params Expression<Func<T, object>>[] expressions)
146150
{
147-
Self.Fields = expressions.Select(e => (PropertyPathMarker) e).ToList();
151+
Self.Fields = expressions.Select(e => (PropertyPathMarker)e).ToList();
148152
return this;
149153
}
150154

@@ -154,7 +158,7 @@ public MultiGetOperationDescriptor<T> Fields(params Expression<Func<T, object>>[
154158
/// </summary>
155159
public MultiGetOperationDescriptor<T> Fields(params string[] fields)
156160
{
157-
Self.Fields = fields.Select(f => (PropertyPathMarker) f).ToList();
161+
Self.Fields = fields.Select(f => (PropertyPathMarker)f).ToList();
158162
return this;
159163
}
160164

@@ -166,5 +170,27 @@ public MultiGetOperationDescriptor<T> Document(T document)
166170
Self.Document = document;
167171
return this;
168172
}
173+
174+
// Only used for the MLT query for providing a different analyzer per
175+
// artificial document field.
176+
// TODO: For 2.0, we should consider decoupling IMultiGetOperation from
177+
// MoreLikeThisQuery and have a dedicatd MoreLikeThisDocument object.
178+
public MultiGetOperationDescriptor<T> PerFieldAnalyzer(Func<FluentDictionary<Expression<Func<T, object>>, string>, FluentDictionary<Expression<Func<T, object>>, string>> analyzerSelector)
179+
{
180+
var d = new FluentDictionary<Expression<Func<T, object>>, string>();
181+
analyzerSelector(d);
182+
Self.PerFieldAnalyzer = d.ToDictionary(x => PropertyPathMarker.Create(x.Key), x => x.Value);
183+
return this;
184+
}
185+
186+
// Only used for the MLT query for providing a different analyzer per
187+
// artificial document field.
188+
// TODO: For 2.0, we should consider decoupling IMultiGetOperation from
189+
// MoreLikeThisQuery and have a dedicatd MoreLikeThisDocument object.
190+
public MultiGetOperationDescriptor<T> PerFieldAnalyzer(Func<FluentDictionary<PropertyPathMarker, string>, FluentDictionary<PropertyPathMarker, string>> analyzerSelector)
191+
{
192+
Self.PerFieldAnalyzer = analyzerSelector(new FluentDictionary<PropertyPathMarker, string>());
193+
return this;
194+
}
169195
}
170196
}

src/Nest/DSL/TermVectorDescriptor.cs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Linq;
44
using Elasticsearch.Net;
55
using Newtonsoft.Json;
6+
using System.Linq.Expressions;
67

78
namespace Nest
89
{
@@ -13,6 +14,9 @@ public interface ITermvectorRequest : IDocumentOptionalPath<TermvectorRequestPar
1314
/// </summary>
1415
[JsonProperty("doc")]
1516
object Document { get; set; }
17+
18+
[JsonProperty("per_field_analyzer")]
19+
IDictionary<PropertyPathMarker, string> PerFieldAnalyzer { get; set; }
1620
}
1721

1822
public interface ITermvectorRequest<T> : ITermvectorRequest where T : class { }
@@ -35,13 +39,17 @@ protected override void UpdatePathInfo(IConnectionSettingsValues settings, Elast
3539
}
3640

3741
public object Document { get; set; }
42+
43+
public IDictionary<PropertyPathMarker, string> PerFieldAnalyzer { get; set; }
3844
}
3945

4046
public partial class TermvectorRequest<T> : DocumentOptionalPathBase<TermvectorRequestParameters, T>, ITermvectorRequest<T>
4147
where T : class
4248
{
4349
object ITermvectorRequest.Document { get; set; }
4450

51+
IDictionary<PropertyPathMarker, string> ITermvectorRequest.PerFieldAnalyzer { get; set; }
52+
4553
public TermvectorRequest(string id) : base(id) { }
4654

4755
public TermvectorRequest(long id) : base(id) { }
@@ -58,14 +66,30 @@ public partial class TermvectorDescriptor<T> : DocumentOptionalPathDescriptor<Te
5866
, ITermvectorRequest
5967
where T : class
6068
{
69+
private ITermvectorRequest Self { get { return this; } }
70+
6171
object ITermvectorRequest.Document { get; set; }
6272

73+
IDictionary<PropertyPathMarker, string> ITermvectorRequest.PerFieldAnalyzer { get; set; }
74+
6375
public TermvectorDescriptor<T> Document<TDocument>(TDocument document) where TDocument : class
6476
{
65-
((ITermvectorRequest) this).Document = document;
77+
Self.Document = document;
78+
return this;
79+
}
80+
public TermvectorDescriptor<T> PerFieldAnalyzer(Func<FluentDictionary<Expression<Func<T, object>>, string>, FluentDictionary<Expression<Func<T, object>>, string>> analyzerSelector)
81+
{
82+
var d = new FluentDictionary<Expression<Func<T, object>>, string>();
83+
analyzerSelector(d);
84+
Self.PerFieldAnalyzer = d.ToDictionary(x => PropertyPathMarker.Create(x.Key), x => x.Value);
6685
return this;
6786
}
6887

88+
public TermvectorDescriptor<T> PerFieldAnalyzer(Func<FluentDictionary<PropertyPathMarker, string>, FluentDictionary<PropertyPathMarker, string>> analyzerSelector)
89+
{
90+
Self.PerFieldAnalyzer = analyzerSelector(new FluentDictionary<PropertyPathMarker, string>());
91+
return this;
92+
}
6993
protected override void UpdatePathInfo(IConnectionSettingsValues settings, ElasticsearchPathInfo<TermvectorRequestParameters> pathInfo)
7094
{
7195
TermvectorPathInfo.Update(settings, pathInfo, this);

src/Tests/Nest.Tests.Integration/Core/TermVectors/TermVectorTests.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,23 @@ public void TermVectorDocument()
3333
AssertContentsVectors(result);
3434
}
3535

36+
[Test]
37+
[SkipVersion("0 - 1.4.9", "Per field analyzers added in ES 1.5")]
38+
public void TermVectorDocumentWithPerFieldAnalyzers()
39+
{
40+
var document = NestTestData.Data.FirstOrDefault(d => d.Id == 1);
41+
var result = Client.TermVector<ElasticsearchProject>(s => s
42+
.Document(document)
43+
.Fields(ep => ep.Content)
44+
.PerFieldAnalyzer(pfa => pfa
45+
.Add(p => p.Name, "keyword")
46+
.Add(p => p.Country, "simple")
47+
)
48+
);
49+
50+
AssertContentsVectors(result);
51+
}
52+
3653
private static void AssertContentsVectors(ITermVectorResponse result)
3754
{
3855
result.IsValid.Should().BeTrue();

src/Tests/Nest.Tests.Unit/Search/Query/Singles/MoreLikeThisQueryJson.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,12 @@ public void MoreLikeThisWithDocuments()
5858
.Documents(d => d
5959
.Get(1, g => g.Fields(p => p.Product.Name).Routing("routing_value"))
6060
.Get<Person>("some-string-id", g => g.Routing("routing_value").Type("people").Index("different_index"))
61-
.Get<MoreLikeThisTestDoc>(g => g.Document(new MoreLikeThisTestDoc { Name = "elasticsearch", Text = "foo" }))
61+
.Get<MoreLikeThisTestDoc>(g => g
62+
.Document(new MoreLikeThisTestDoc { Name = "elasticsearch", Text = "foo" })
63+
.PerFieldAnalyzer(pfa => pfa
64+
.Add(p => p.Name, "keyword")
65+
)
66+
)
6267
.Document<MoreLikeThisTestDoc>(new MoreLikeThisTestDoc { Name = "nest" })
6368
.Document<MoreLikeThisTestDoc>(new MoreLikeThisTestDoc { Name = "foo" }, "myindex", "mytype")
6469
);
@@ -88,6 +93,9 @@ public void MoreLikeThisWithDocuments()
8893
doc: {
8994
name: ""elasticsearch"",
9095
text: ""foo""
96+
},
97+
per_field_analyzer: {
98+
name: ""keyword""
9199
}
92100
},
93101
{

0 commit comments

Comments
 (0)