Skip to content

Commit 0a8352c

Browse files
committed
Add SuffixExpressionVisitor to support appending suffixes to lambda expressions
Add documentation to demonstrate usage Closes #1795
1 parent da3d64e commit 0a8352c

File tree

8 files changed

+188
-83
lines changed

8 files changed

+188
-83
lines changed

docs/asciidoc/ClientConcepts/HighLevel/Inferrence/FieldInference.doc.asciidoc

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Expect("name")
2323
.WhenSerializing(fieldExpression)
2424
.WhenSerializing(fieldString);
2525
----
26-
Therefor you can also implicitly convert strings and expressions to Field's
26+
Therefore you can also implicitly convert strings and expressions to Field's
2727

2828
[source, csharp]
2929
----
@@ -52,7 +52,7 @@ but for expressions this is still rather involved
5252

5353
[source, csharp]
5454
----
55-
var fieldExpression = Field<Project>(p => p.Name);
55+
var fieldExpression = Infer.Field<Project>(p => p.Name);
5656
----
5757
Using static imports in c# 6 this can be even shortened:
5858
using static Nest.Static;
@@ -175,6 +175,36 @@ var suffix = "unanalyzed";
175175
Expect("metadata.var.unanalyzed").WhenSerializing(Field<Project>(p => p.Metadata[variable].Suffix(suffix)));
176176
Expect("metadata.var.created.unanalyzed").WhenSerializing(Field<Project>(p => p.Metadata[variable].Created.Suffix(suffix)));
177177
----
178+
179+
Suffixes can be appended to expressions. This is useful in cases where you want to apply the same suffix
180+
to a list of fields
181+
182+
183+
184+
[source, csharp]
185+
----
186+
var expressions = new List<Expression<Func<Project, object>>>
187+
{
188+
p => p.Name,
189+
p => p.Description,
190+
p => p.CuratedTags.First().Name,
191+
p => p.LeadDeveloper.FirstName
192+
};
193+
----
194+
append the suffix "raw" to each expression
195+
196+
[source, csharp]
197+
----
198+
var fieldExpressions =
199+
expressions.Select<Expression<Func<Project, object>>, Field>(e => e.AppendSuffix("raw")).ToList();
200+
----
201+
[source, csharp]
202+
----
203+
Expect("name.raw").WhenSerializing(fieldExpressions[0]);
204+
Expect("description.raw").WhenSerializing(fieldExpressions[1]);
205+
Expect("curatedTags.name.raw").WhenSerializing(fieldExpressions[2]);
206+
Expect("leadDeveloper.firstName.raw").WhenSerializing(fieldExpressions[3]);
207+
----
178208
Annotations
179209

180210
When using NEST's property attributes you can specify a new name for the properties

src/Benchmarking/project.lock.json

Lines changed: 36 additions & 36 deletions
Large diffs are not rendered by default.

src/Elasticsearch.Net/project.lock.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2025,7 +2025,7 @@
20252025
"System.Dynamic.Runtime/4.0.11-beta-23516": {
20262026
"type": "package",
20272027
"serviceable": true,
2028-
"sha512": "ypkxS0e+yUw7F6JEwuB22u0qqruMeZFOmtcImh2efDHpTAuhF2FOqCDJ7f4qLf9yomVvB4kjkZ6xGunbIQryxQ==",
2028+
"sha512": "C2GXB20I5vMcO4wemZr5pEjwwEb6H6zVkwF12JSUhripKBIKgI0YKpfp9glyDSL903cYgIXAztMQDajwCR0PmA==",
20292029
"files": [
20302030
"lib/DNXCore50/System.Dynamic.Runtime.dll",
20312031
"lib/MonoAndroid10/_._",
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using System;
2+
using System.Linq.Expressions;
3+
4+
namespace Nest
5+
{
6+
public static class ExpressionExtensions
7+
{
8+
/// <summary>
9+
/// Appends <paramref name="suffix"/> to the path separating it with a dot.
10+
/// This is especially useful with multi fields.
11+
/// </summary>
12+
/// <param name="expression">the expression to which the suffix should be applied</param>
13+
/// <param name="suffix">the suffix</param>
14+
public static Expression<Func<T, object>> AppendSuffix<T>(this Expression<Func<T, object>> expression, string suffix)
15+
{
16+
var newBody = new SuffixExpressionVisitor(suffix).Visit(expression.Body);
17+
return Expression.Lambda<Func<T, object>>(newBody, expression.Parameters[0]);
18+
}
19+
20+
/// <summary>
21+
/// Calls <see cref="SuffixExtensions.Suffix"/> on a member expression.
22+
/// </summary>
23+
private class SuffixExpressionVisitor : ExpressionVisitor
24+
{
25+
private readonly string suffix;
26+
27+
public SuffixExpressionVisitor(string suffix)
28+
{
29+
this.suffix = suffix;
30+
}
31+
32+
protected override Expression VisitMember(MemberExpression node)
33+
{
34+
return Expression.Call(
35+
typeof(SuffixExtensions),
36+
nameof(SuffixExtensions.Suffix),
37+
null,
38+
node,
39+
Expression.Constant(suffix));
40+
}
41+
42+
protected override Expression VisitUnary(UnaryExpression node)
43+
{
44+
return node;
45+
}
46+
}
47+
}
48+
}

src/Nest/project.lock.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2037,7 +2037,7 @@
20372037
"runtime.any.System.Linq.Expressions/4.0.11-beta-23516": {
20382038
"type": "package",
20392039
"serviceable": true,
2040-
"sha512": "4sPxQCjllMJ1uZNlwz/EataPyHSH+AqSDlOIPPqcy/88R2B+abfhPPC78rd7gvHp8KmMX4qbJF6lcCeDIQpmVg==",
2040+
"sha512": "P5nzo1Ye0GxB4BYdWian6Y427eTrhn1JS3jLWZq5bMWVn8hS/OIfyylASN0A/qqeLn4rGA0fOzmJSYqFSKvxgQ==",
20412041
"files": [
20422042
"lib/DNXCore50/System.Linq.Expressions.dll",
20432043
"lib/MonoAndroid10/_._",
@@ -2345,7 +2345,7 @@
23452345
"System.Dynamic.Runtime/4.0.11-beta-23516": {
23462346
"type": "package",
23472347
"serviceable": true,
2348-
"sha512": "ypkxS0e+yUw7F6JEwuB22u0qqruMeZFOmtcImh2efDHpTAuhF2FOqCDJ7f4qLf9yomVvB4kjkZ6xGunbIQryxQ==",
2348+
"sha512": "C2GXB20I5vMcO4wemZr5pEjwwEb6H6zVkwF12JSUhripKBIKgI0YKpfp9glyDSL903cYgIXAztMQDajwCR0PmA==",
23492349
"files": [
23502350
"lib/DNXCore50/System.Dynamic.Runtime.dll",
23512351
"lib/MonoAndroid10/_._",
@@ -2599,7 +2599,7 @@
25992599
"System.Linq.Expressions/4.0.11-beta-23516": {
26002600
"type": "package",
26012601
"serviceable": true,
2602-
"sha512": "YEl5oyF5fifLbHHP099cvb/6f2r2h1QVHzoaoINPHOZtpNec+RfqvzETXcYDIdHT7l+bBAYsBuVUkBgfQEoYfQ==",
2602+
"sha512": "FtKytB13HabzrSvrAgBgOOnG2uxJO4s7zvP5Sk0NS3bwbJUyb5AP1p4897UWnLiB6C95jI4nIkZps51sa9In8g==",
26032603
"files": [
26042604
"lib/MonoAndroid10/_._",
26052605
"lib/MonoTouch10/_._",

src/Tests/ClientConcepts/HighLevel/Inferrence/FieldInference.doc.cs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34
using System.Linq.Expressions;
45
using System.Reflection;
@@ -41,7 +42,7 @@ public void UsingConstructors()
4142
.WhenSerializing(fieldString);
4243
}
4344

44-
/** Therefor you can also implicitly convert strings and expressions to Field's */
45+
/** Therefore you can also implicitly convert strings and expressions to Field's */
4546
[U]
4647
public void ImplicitConversion()
4748
{
@@ -63,7 +64,7 @@ public void UsingStaticPropertyField()
6364
Field fieldString = "name";
6465

6566
/** but for expressions this is still rather involved */
66-
var fieldExpression = Field<Project>(p => p.Name);
67+
var fieldExpression = Infer.Field<Project>(p => p.Name);
6768

6869
/** Using static imports in c# 6 this can be even shortened:
6970
using static Nest.Static;
@@ -139,6 +140,32 @@ public void ComplexFieldNameExpressions()
139140
Expect("metadata.var.created.unanalyzed").WhenSerializing(Field<Project>(p => p.Metadata[variable].Created.Suffix(suffix)));
140141
}
141142

143+
/**
144+
* Suffixes can be appended to expressions. This is useful in cases where you want to apply the same suffix
145+
* to a list of fields
146+
*/
147+
[U]
148+
public void AppendingSuffixToExpressions()
149+
{
150+
/** */
151+
var expressions = new List<Expression<Func<Project, object>>>
152+
{
153+
p => p.Name,
154+
p => p.Description,
155+
p => p.CuratedTags.First().Name,
156+
p => p.LeadDeveloper.FirstName
157+
};
158+
159+
/** append the suffix "raw" to each expression */
160+
var fieldExpressions =
161+
expressions.Select<Expression<Func<Project, object>>, Field>(e => e.AppendSuffix("raw")).ToList();
162+
163+
Expect("name.raw").WhenSerializing(fieldExpressions[0]);
164+
Expect("description.raw").WhenSerializing(fieldExpressions[1]);
165+
Expect("curatedTags.name.raw").WhenSerializing(fieldExpressions[2]);
166+
Expect("leadDeveloper.firstName.raw").WhenSerializing(fieldExpressions[3]);
167+
}
168+
142169
/** Annotations
143170
*
144171
* When using NEST's property attributes you can specify a new name for the properties

0 commit comments

Comments
 (0)