Skip to content

Commit e63ea70

Browse files
committed
Cherry pick Field expression caching from 2.x
Commits 99dac2a and de2a241 See #2048
1 parent c523535 commit e63ea70

File tree

8 files changed

+383
-192
lines changed

8 files changed

+383
-192
lines changed

src/Nest/CommonAbstractions/Extensions/ExpressionExtensions.cs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System;
2+
using System.Linq;
23
using System.Linq.Expressions;
4+
using System.Text.RegularExpressions;
35

46
namespace Nest
57
{
@@ -44,5 +46,26 @@ protected override Expression VisitUnary(UnaryExpression node)
4446
return node;
4547
}
4648
}
49+
50+
private static readonly Regex ExpressionRegex = new Regex(@"^\s*(.*)\s*\=\>\s*\1\.");
51+
private static readonly Regex MemberExpressionRegex = new Regex(@"^[^\.]*\.");
52+
53+
internal static object ComparisonValueFromExpression(this Expression expression, out Type type)
54+
{
55+
type = null;
56+
57+
if (expression == null) return null;
58+
59+
var lambda = expression as LambdaExpression;
60+
if (lambda == null)
61+
return ExpressionRegex.Replace(expression.ToString(), string.Empty);
62+
63+
type = lambda.Parameters.FirstOrDefault()?.Type;
64+
65+
var memberExpression = lambda.Body as MemberExpression;
66+
return memberExpression != null
67+
? MemberExpressionRegex.Replace(memberExpression.ToString(), string.Empty)
68+
: ExpressionRegex.Replace(expression.ToString(), string.Empty);
69+
}
4770
}
48-
}
71+
}

src/Nest/CommonAbstractions/Infer/Field/Field.cs

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,17 @@ namespace Nest
1010
[ContractJsonConverter(typeof(FieldJsonConverter))]
1111
public class Field : IEquatable<Field>, IUrlParameter
1212
{
13-
public string Name { get; private set; }
13+
private readonly object _comparisonValue;
14+
private readonly Type _type;
1415

15-
public Expression Expression { get; private set; }
16+
public string Name { get; }
1617

17-
private Type Type { get; }
18+
public Expression Expression { get; }
1819

19-
public PropertyInfo Property { get; private set; }
20+
public PropertyInfo Property { get; }
2021

2122
public double? Boost { get; set; }
2223

23-
private object ComparisonValue { get; }
24-
2524
public bool CachableExpression { get; }
2625

2726
public Fields And<T>(Expression<Func<T, object>> field) where T : class =>
@@ -35,7 +34,7 @@ public Field(string name, double? boost = null)
3534
double? b;
3635
Name = ParseFieldName(name, out b);
3736
Boost = b ?? boost;
38-
ComparisonValue = Name;
37+
_comparisonValue = Name;
3938
}
4039

4140
public Field(Expression expression, double? boost = null)
@@ -44,8 +43,8 @@ public Field(Expression expression, double? boost = null)
4443
Expression = expression;
4544
Boost = boost;
4645
Type type;
47-
ComparisonValue = ComparisonValueFromExpression(expression, out type);
48-
Type = type;
46+
_comparisonValue = expression.ComparisonValueFromExpression(out type);
47+
_type = type;
4948
CachableExpression = !new HasConstantExpressionVisitor(expression).Found;
5049
}
5150

@@ -54,8 +53,8 @@ public Field(PropertyInfo property, double? boost = null)
5453
if (property == null) return;
5554
Property = property;
5655
Boost = boost;
57-
ComparisonValue = property;
58-
Type = property.DeclaringType;
56+
_comparisonValue = property;
57+
_type = property.DeclaringType;
5958
}
6059

6160
private static string ParseFieldName(string name, out double? boost)
@@ -72,20 +71,6 @@ private static string ParseFieldName(string name, out double? boost)
7271
return name;
7372
}
7473

75-
private static object ComparisonValueFromExpression(Expression expression, out Type type)
76-
{
77-
type = null;
78-
79-
var lambda = expression as LambdaExpression;
80-
if (lambda == null)
81-
return expression.ToString();
82-
83-
type = lambda.Parameters.FirstOrDefault()?.Type;
84-
85-
var memberExpression = lambda.Body as MemberExpression;
86-
return memberExpression?.ToString() ?? expression.ToString();
87-
}
88-
8974
public static implicit operator Field(string name)
9075
{
9176
return name.IsNullOrEmpty() ? null : new Field(name);
@@ -103,19 +88,37 @@ public static implicit operator Field(PropertyInfo property)
10388

10489
public override int GetHashCode()
10590
{
106-
var hashCode = ComparisonValue?.GetHashCode() ?? 0;
107-
hashCode = (hashCode*397) ^ (Type?.GetHashCode() ?? 0);
108-
return hashCode;
91+
unchecked
92+
{
93+
var hashCode = _comparisonValue?.GetHashCode() ?? 0;
94+
hashCode = (hashCode * 397) ^ (_type?.GetHashCode() ?? 0);
95+
return hashCode;
96+
}
10997
}
11098

111-
bool IEquatable<Field>.Equals(Field other) => Equals(other);
99+
public bool Equals(Field other)
100+
{
101+
return _type != null
102+
? other != null && _type == other._type && _comparisonValue.Equals(other._comparisonValue)
103+
: other != null && _comparisonValue.Equals(other._comparisonValue);
104+
}
112105

113106
public override bool Equals(object obj)
114107
{
115-
var other = obj as Field;
116-
if (other == null)
117-
return false;
118-
return ComparisonValue.Equals(other.ComparisonValue);
108+
if (ReferenceEquals(null, obj)) return false;
109+
if (ReferenceEquals(this, obj)) return true;
110+
if (obj.GetType() != GetType()) return false;
111+
return this.Equals(obj as Field);
112+
}
113+
114+
public static bool operator ==(Field x, Field y)
115+
{
116+
return Equals(x, y);
117+
}
118+
119+
public static bool operator !=(Field x, Field y)
120+
{
121+
return !(x == y);
119122
}
120123

121124
string IUrlParameter.GetString(IConnectionConfigurationValues settings)

src/Nest/CommonAbstractions/Infer/Field/FieldExpressionVisitor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ protected override Expression VisitConstant(ConstantExpression node)
6565

6666
internal class FieldExpressionVisitor : ExpressionVisitor
6767
{
68-
private Stack<string> _stack = new Stack<string>();
68+
private readonly Stack<string> _stack = new Stack<string>();
6969

70-
private IConnectionSettingsValues _settings;
70+
private readonly IConnectionSettingsValues _settings;
7171

7272
public FieldExpressionVisitor(IConnectionSettingsValues settings)
7373
{

src/Nest/CommonAbstractions/Infer/Field/FieldResolver.cs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,24 +42,29 @@ private string ResolveFieldName(Field field)
4242
return this.Resolve(field.Expression, field.Property);
4343
}
4444

45-
string f;
46-
if (this.Fields.TryGetValue(field, out f))
47-
return f;
45+
string fieldName;
46+
if (this.Fields.TryGetValue(field, out fieldName))
47+
return fieldName;
4848

49-
f = this.Resolve(field.Expression, field.Property);
50-
this.Fields.TryAdd(field, f);
51-
return f;
49+
fieldName = this.Resolve(field.Expression, field.Property);
50+
this.Fields.TryAdd(field, fieldName);
51+
return fieldName;
5252
}
5353

5454
public string Resolve(PropertyName property)
5555
{
5656
if (property.IsConditionless()) return null;
57-
if (!property.Name.IsNullOrEmpty())
58-
return property.Name;
57+
if (!property.Name.IsNullOrEmpty()) return property.Name;
58+
59+
if (property.Expression != null && !property.CacheableExpression)
60+
{
61+
return this.Resolve(property.Expression, property.Property);
62+
}
5963

6064
string propertyName;
6165
if (this.Properties.TryGetValue(property, out propertyName))
6266
return propertyName;
67+
6368
propertyName = this.Resolve(property.Expression, property.Property, true);
6469
this.Properties.TryAdd(property, propertyName);
6570
return propertyName;

src/Nest/CommonAbstractions/Infer/PropertyName/PropertyName.cs

Lines changed: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,56 +8,83 @@ namespace Nest
88
[ContractJsonConverter(typeof(PropertyNameJsonConverter))]
99
public class PropertyName : IEquatable<PropertyName>, IUrlParameter
1010
{
11-
public string Name { get; set; }
12-
public Expression Expression { get; set; }
13-
public PropertyInfo Property { get; set; }
11+
public string Name { get; }
12+
public Expression Expression { get; }
13+
public PropertyInfo Property { get; }
14+
public bool CacheableExpression { get; }
1415

15-
private object ComparisonValue;
16+
private readonly object _comparisonValue;
17+
private readonly Type _type;
18+
19+
public PropertyName(string name)
20+
{
21+
Name = name;
22+
_comparisonValue = name;
23+
}
24+
25+
public PropertyName(Expression expression)
26+
{
27+
Type type;
28+
Expression = expression;
29+
CacheableExpression = !new HasConstantExpressionVisitor(expression).Found;
30+
_comparisonValue = expression.ComparisonValueFromExpression(out type);
31+
_type = type;
32+
}
33+
34+
public PropertyName(PropertyInfo property)
35+
{
36+
Property = property;
37+
_comparisonValue = property;
38+
}
1639

1740
public static implicit operator PropertyName(string name)
1841
{
19-
return name == null ? null : new PropertyName
20-
{
21-
Name = name,
22-
ComparisonValue = name
23-
};
42+
return name == null ? null : new PropertyName(name);
2443
}
2544

2645
public static implicit operator PropertyName(Expression expression)
2746
{
28-
return expression == null ? null : new PropertyName
29-
{
30-
Expression = expression,
31-
ComparisonValue = ((expression as LambdaExpression)?.Body as MemberExpression)?.Member.Name ?? expression.ToString()
32-
};
47+
return expression == null ? null : new PropertyName(expression);
3348
}
3449

3550
public static implicit operator PropertyName(PropertyInfo property)
3651
{
37-
return property == null ? null : new PropertyName
38-
{
39-
Property = property,
40-
ComparisonValue = property
41-
};
52+
return property == null ? null : new PropertyName(property);
4253
}
4354

4455
public override int GetHashCode()
4556
{
46-
return ComparisonValue?.GetHashCode() ?? 0;
57+
unchecked
58+
{
59+
var hashCode = _comparisonValue?.GetHashCode() ?? 0;
60+
hashCode = (hashCode * 397) ^ (_type?.GetHashCode() ?? 0);
61+
return hashCode;
62+
}
4763
}
4864

49-
bool IEquatable<PropertyName>.Equals(PropertyName other)
65+
public bool Equals(PropertyName other)
5066
{
51-
return Equals(other);
67+
return _type != null
68+
? other != null && _type == other._type && _comparisonValue.Equals(other._comparisonValue)
69+
: other != null && _comparisonValue.Equals(other._comparisonValue);
5270
}
5371

5472
public override bool Equals(object obj)
5573
{
56-
var other = obj as PropertyName;
57-
if (other == null)
58-
return false;
74+
if (ReferenceEquals(null, obj)) return false;
75+
if (ReferenceEquals(this, obj)) return true;
76+
if (obj.GetType() != GetType()) return false;
77+
return this.Equals(obj as PropertyName);
78+
}
5979

60-
return ComparisonValue.Equals(other.ComparisonValue);
80+
public static bool operator ==(PropertyName x, PropertyName y)
81+
{
82+
return Equals(x, y);
83+
}
84+
85+
public static bool operator !=(PropertyName x, PropertyName y)
86+
{
87+
return !(x == y);
6188
}
6289

6390
string IUrlParameter.GetString(IConnectionConfigurationValues settings)

0 commit comments

Comments
 (0)