Skip to content

Commit 90fab3c

Browse files
russcamMpdreamz
authored andcommitted
Add additional methods for combining Field values and building Fields (#2419)
Regenerate documentation
1 parent c687177 commit 90fab3c

File tree

14 files changed

+729
-102
lines changed

14 files changed

+729
-102
lines changed

docs/client-concepts/connection-pooling/building-blocks/request-pipelines.asciidoc

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,16 +129,16 @@ var response = new
129129
host = "127.0.0.1",
130130
ip = "127.0.01",
131131
version = "5.0.0-alpha3",
132-
build = "e455fd0",
133-
http_address = "127.0.0.1:9200",
134-
settings = new JObject
132+
build_hash = "e455fd0",
133+
roles = new List<string>(),
134+
http = new
135135
{
136-
{"client.type", "node"},
137-
{"cluster.name", "elasticsearch"},
138-
{"config.ignore_system_properties", "true"},
139-
{"name", "Node Name 1"},
140-
{"path.home", "c:\\elasticsearch\\elasticsearch"},
141-
{"path.logs", "c:/ elasticsearch/logs"}
136+
bound_address = new[] { "127.0.0.1:9200" }
137+
},
138+
settings = new Dictionary<string, object>
139+
{
140+
{ "cluster.name", "elasticsearch" },
141+
{ "node.name", "Node Name 1" }
142142
}
143143
}
144144
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/master
2+
3+
:github: https://github.com/elastic/elasticsearch-net
4+
5+
:nuget: https://www.nuget.org/packages
6+
7+
////
8+
IMPORTANT NOTE
9+
==============
10+
This file has been generated from https://github.com/elastic/elasticsearch-net/tree/master/src/Tests/ClientConcepts/ConnectionPooling/Sniffing/AddressParsing.doc.cs.
11+
If you wish to submit a PR for any spelling mistakes, typos or grammatical errors for this file,
12+
please modify the original csharp file found at the link and submit the PR with that change. Thanks!
13+
////
14+
15+
[[address-parsing]]
16+
== Address Parsing
17+
18+
[source,csharp]
19+
----
20+
var testcases = new[,]
21+
{
22+
{"[::1]:9200", "[::1]", "9200"},
23+
{"192.168.2.1:231", "192.168.2.1", "231"},
24+
{"[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80", "[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]", "80"},
25+
{"[1080:0:0:0:8:800:200C:417A]:1234", "[1080:0:0:0:8:800:200C:417A]", "1234"},
26+
{"[3ffe:2a00:100:7031::1]:1", "[3ffe:2a00:100:7031::1]", "1"},
27+
{"[1080::8:800:200C:417A]:123", "[1080::8:800:200C:417A]", "123"},
28+
{"[::192.9.5.5]:12", "[::192.9.5.5]", "12"},
29+
{"[::FFFF:129.144.52.38]:80", "[::FFFF:129.144.52.38]", "80"},
30+
{"[2010:836B:4179::836B:4179]:34533", "[2010:836B:4179::836B:4179]", "34533"}
31+
};
32+
var address = testcases[i, 0];
33+
var ip = testcases[i, 1];
34+
var port = testcases[i, 2];
35+
var match = Elasticsearch.Net.SniffResponse.AddressRegex.Match(address);
36+
match.Success.Should().BeTrue();
37+
match.Groups["ip"].Value.ShouldBeEquivalentTo(ip);
38+
match.Groups["port"].Value.ShouldBeEquivalentTo(port);
39+
----
40+

docs/client-concepts/high-level/inference/field-inference.asciidoc

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ please modify the original csharp file found at the link and submit the PR with
1515
[[field-inference]]
1616
== Field Inference
1717

18-
Several places in the Elasticsearch API expect the path to a field from your original source document as a string.
18+
Several places in the Elasticsearch API expect the path to a field from your original source document, as a string value.
1919
NEST allows you to use C# expressions to strongly type these field path strings.
2020

2121
These expressions are assigned to a type called `Field` and there are several ways to create an instance of one
2222

2323
=== Constructor
2424

25-
Using the constructor directly is possible _but_ rather involved
25+
Using the constructor directly is possible _but_ can get rather involved when resolving from a member access lambda expression
2626

2727
[source,csharp]
2828
----
@@ -42,6 +42,8 @@ When using the constructor and passing a value for `Name`, `Property` or `Expres
4242

4343
* getting the hash code for a `Field` instance
4444

45+
IMPORTANT: Boost values are not taken into account when determining equality.
46+
4547
[source,csharp]
4648
----
4749
var fieldStringWithBoostTwo = new Field("name^2");
@@ -66,34 +68,12 @@ fieldStringWithBoostTwo.Should().Be(fieldStringWithBoostThree); <1>
6668
----
6769
<1> <<field-name-with-boost,Fields can constructed with a name that contains a boost>>
6870

69-
=== Implicit Conversion
70-
71-
As you can see from the previous examples, using the constructor is rather involved and cumbersome.
72-
Because of this, you can also implicitly convert strings and expressions to a `Field`
73-
74-
[source,csharp]
75-
----
76-
Field fieldString = "name";
77-
----
78-
79-
but for expressions this is _still_ rather involved
80-
81-
[source,csharp]
82-
----
83-
Expression<Func<Project, object>> expression = p => p.Name;
84-
85-
Field fieldExpression = expression;
86-
87-
Expect("name")
88-
.WhenSerializing(fieldExpression)
89-
.WhenSerializing(fieldString);
90-
----
91-
9271
[[field-name-with-boost]]
9372
=== Field Names with Boost
9473

9574
When specifying a `Field` name, the name can include a boost value; NEST will split the name and boost
96-
value and set the `Boost` property
75+
value and set the `Boost` property; a boost value as part of the string takes precedence over a boost
76+
value that may also be passed as the second constructor argument
9777

9878
[source,csharp]
9979
----
@@ -117,6 +97,28 @@ fieldStringCreate.Boost.Should().Be(2);
11797
----
11898
<1> NEST will take the boost from the name
11999

100+
=== Implicit Conversion
101+
102+
As well as using the constructor, you can also implicitly convert `string`, `PropertyInfo` and member access lambda expressions to a `Field`.
103+
For expressions however, this is _still_ rather involved as the expression first needs to be assigned to a variable that explicitly specifies
104+
the expression delegate type.
105+
106+
[source,csharp]
107+
----
108+
Field fieldString = "name";
109+
110+
Field fieldProperty = typeof(Project).GetProperty(nameof(Project.Name));
111+
112+
Expression<Func<Project, object>> expression = p => p.Name;
113+
114+
Field fieldExpression = expression;
115+
116+
Expect("name")
117+
.WhenSerializing(fieldString)
118+
.WhenSerializing(fieldProperty)
119+
.WhenSerializing(fieldExpression);
120+
----
121+
120122
[[nest-infer]]
121123
=== Using Nest.Infer
122124

@@ -135,7 +137,7 @@ var fieldExpression = Infer.Field<Project>(p => p.Name);
135137
----
136138

137139
this can be even shortened even further using a https://msdn.microsoft.com/en-us/library/sf0df423.aspx#Anchor_0[static import in C# 6] i.e.
138-
`using static Nest.Infer;`
140+
`using static Nest.Infer;` using directive
139141

140142
[source,csharp]
141143
----
@@ -174,7 +176,7 @@ Expect("name^2.1")
174176
[[camel-casing]]
175177
=== Field name casing
176178

177-
By default, NEST will camel-case **all** field names to better align with typical
179+
By default, NEST https://en.wikipedia.org/wiki/Camel_case[camelcases] **all** field names to better align with typical
178180
javascript/json conventions
179181

180182
using `DefaultFieldNameInferrer()` on ConnectionSettings you can change this behavior

docs/code-standards/descriptors.asciidoc

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ var descriptors = from t in typeof(DescriptorBase<,>).Assembly().Types()
2424
where t.IsClass()
2525
&& t.Name.Contains("Descriptor")
2626
&& !notDescriptors.Contains(t.Name)
27-
&& !t.GetInterfaces().Any(i => i == typeof(IDescriptor))
27+
&& t.GetInterfaces().All(i => i != typeof(IDescriptor))
2828
select t.FullName;
2929
descriptors.Should().BeEmpty();
3030
----
@@ -38,6 +38,37 @@ var descriptors =
3838
where t.IsClass() && typeof(IDescriptor).IsAssignableFrom(t)
3939
select t;
4040
41+
var exclusions = new Dictionary<Type, Type>
42+
{
43+
{ typeof(QueryContainerDescriptor<>), typeof(QueryContainer) },
44+
{ typeof(ConditionDescriptor), typeof(ConditionContainer) },
45+
{ typeof(TriggerDescriptor), typeof(TriggerContainer) },
46+
{ typeof(TransformDescriptor), typeof(TransformContainer) },
47+
{ typeof(InputDescriptor), typeof(InputContainer) },
48+
{ typeof(FluentDictionary<,>), typeof(FluentDictionary<,>) }
49+
};
50+
51+
Func<Type, Type, bool> exclude = (first, second) =>
52+
{
53+
var key = first.IsGenericType()
54+
? first.GetGenericTypeDefinition()
55+
: first;
56+
57+
Type value;
58+
if (!exclusions.TryGetValue(key, out value))
59+
return false;
60+
61+
return second.IsGenericType()
62+
? second.GetGenericTypeDefinition() == value
63+
: value.IsAssignableFrom(second);
64+
};
65+
66+
var key = first.IsGenericType()
67+
? first.GetGenericTypeDefinition()
68+
: first;
69+
70+
Type value;
71+
4172
var selectorMethods =
4273
from d in descriptors
4374
from m in d.GetMethods()
@@ -50,16 +81,7 @@ var selectorMethods =
5081
where isFunc
5182
let firstFuncArg = type.GetGenericArguments().First()
5283
let secondFuncArg = type.GetGenericArguments().Last()
53-
let isQueryFunc = firstFuncArg.IsGenericType() &&
54-
firstFuncArg.GetGenericTypeDefinition() == typeof(QueryContainerDescriptor<>) &&
55-
typeof(QueryContainer).IsAssignableFrom(secondFuncArg)
56-
where !isQueryFunc
57-
let isFluentDictionaryFunc =
58-
firstFuncArg.IsGenericType() &&
59-
firstFuncArg.GetGenericTypeDefinition() == typeof(FluentDictionary<,>) &&
60-
secondFuncArg.IsGenericType() &&
61-
secondFuncArg.GetGenericTypeDefinition() == typeof(FluentDictionary<,>)
62-
where !isFluentDictionaryFunc
84+
where !exclude(firstFuncArg, secondFuncArg)
6385
let lastArgIsNotInterface = !secondFuncArg.IsInterface()
6486
where lastArgIsNotInterface
6587
select $"{m.Name} on {m.DeclaringType.Name}";
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/master
2+
3+
:github: https://github.com/elastic/elasticsearch-net
4+
5+
:nuget: https://www.nuget.org/packages
6+
7+
////
8+
IMPORTANT NOTE
9+
==============
10+
This file has been generated from https://github.com/elastic/elasticsearch-net/tree/master/src/Tests/CodeStandards/Responses.doc.cs.
11+
If you wish to submit a PR for any spelling mistakes, typos or grammatical errors for this file,
12+
please modify the original csharp file found at the link and submit the PR with that change. Thanks!
13+
////
14+
15+
[[responses]]
16+
== Responses
17+
18+
Every collection property on a Response type should be either IReadOnlyCollection or IReadOnlyDictionary
19+
20+
[source,csharp]
21+
----
22+
var exceptions = new HashSet<PropertyInfo>
23+
{
24+
typeof(ITypeMapping).GetProperty(nameof(ITypeMapping.DynamicDateFormats)),
25+
typeof(ITypeMapping).GetProperty(nameof(ITypeMapping.Meta)),
26+
typeof(TypeMapping).GetProperty(nameof(TypeMapping.DynamicDateFormats)),
27+
typeof(TypeMapping).GetProperty(nameof(TypeMapping.Meta)),
28+
#pragma warning disable 618
29+
typeof(IMultiPercolateResponse).GetProperty(nameof(IMultiPercolateResponse.Responses)),
30+
#pragma warning restore 618
31+
typeof(IBulkResponse).GetProperty(nameof(IBulkResponse.ItemsWithErrors)),
32+
typeof(IMultiSearchResponse).GetProperty(nameof(IMultiSearchResponse.AllResponses)),
33+
};
34+
var responseInterfaceTypes = from t in typeof(IResponse).Assembly().Types()
35+
where t.IsInterface() && typeof(IResponse).IsAssignableFrom(t)
36+
select t;
37+
var ruleBreakers = new List<string>();
38+
var seenTypes = new HashSet<Type>();
39+
40+
foreach (var responseType in responseInterfaceTypes)
41+
{
42+
FindPropertiesBreakingRule(responseType, exceptions, seenTypes, ruleBreakers);
43+
}
44+
----
45+
46+
[source,csharp]
47+
----
48+
var properties = type.GetProperties();
49+
----
50+
51+
[source,csharp]
52+
----
53+
ruleBreakers.Should().BeEmpty();
54+
----
55+
56+
[source,csharp]
57+
----
58+
foreach (var propertyInfo in properties)
59+
{
60+
if (exceptions.Contains(propertyInfo))
61+
continue;
62+
63+
if (typeof(IDictionary).IsAssignableFrom(propertyInfo.PropertyType) ||
64+
typeof(ICollection).IsAssignableFrom(propertyInfo.PropertyType))
65+
{
66+
ruleBreakers.Add($"{type.FullName}.{propertyInfo.Name} is of type {propertyInfo.PropertyType.Name}");
67+
}
68+
else if (propertyInfo.PropertyType.IsGenericType())
69+
{
70+
var genericTypeDefinition = propertyInfo.PropertyType.GetGenericTypeDefinition();
71+
if (genericTypeDefinition == typeof(IDictionary<,>) ||
72+
genericTypeDefinition == typeof(Dictionary<,>) ||
73+
genericTypeDefinition == typeof(IEnumerable<>) ||
74+
genericTypeDefinition == typeof(IList<>) ||
75+
genericTypeDefinition == typeof(ICollection<>))
76+
{
77+
ruleBreakers.Add($"{type.FullName}.{propertyInfo.Name} is of type {propertyInfo.PropertyType.Name}");
78+
}
79+
}
80+
else if (propertyInfo.PropertyType.IsClass() && (propertyInfo.PropertyType.Namespace.StartsWith("Nest") ||
81+
propertyInfo.PropertyType.Namespace.StartsWith("Elasticsearch.Net")))
82+
{
83+
FindPropertiesBreakingRule(propertyInfo.PropertyType, exceptions, seenTypes, ruleBreakers);
84+
}
85+
}
86+
----
87+

0 commit comments

Comments
 (0)