Skip to content

Commit 3764183

Browse files
committed
Merge pull request #1073 from elasticsearch/fix/get-mapping-multiple
Fix/get mapping multiple
2 parents f02ba5e + 9ad5d41 commit 3764183

File tree

12 files changed

+233
-44
lines changed

12 files changed

+233
-44
lines changed

src/CodeGeneration/CodeGeneration.LowLevelClient/Views/IElasticsearchClient.Generated.cshtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace Elasticsearch.Net
1818
///Generated of commit @Model.Commit
1919
///</pre>
2020
///</summary>
21-
public interface IElasticsearchClient
21+
public partial interface IElasticsearchClient
2222
{
2323
//IConnection Connection { get; }
2424
//IConnectionConfigurationValues Settings { get; }

src/Elasticsearch.Net/Elasticsearch.Net.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
<Compile Include="Domain\Response\ElasticsearchServerError.cs" />
7474
<Compile Include="Exceptions\OneToOneServerException.cs" />
7575
<Compile Include="Exceptions\ElasticsearchAuthenticationException.cs" />
76+
<Compile Include="IElasticsearchClient.cs" />
7677
<Compile Include="Obsolete\IndicesDeleteAlias.cs" />
7778
<Compile Include="Obsolete\IndicesPutAlias.cs" />
7879
<Compile Include="Obsolete\IndicesRecoveryStatus.cs" />

src/Elasticsearch.Net/IElasticsearchClient.Generated.cs

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace Elasticsearch.Net
1818
///Generated of commit
1919
///</pre>
2020
///</summary>
21-
public interface IElasticsearchClient
21+
public partial interface IElasticsearchClient
2222
{
2323
//IConnection Connection { get; }
2424
//IConnectionConfigurationValues Settings { get; }
@@ -20080,26 +20080,5 @@ public interface IElasticsearchClient
2008020080

2008120081
Task<ElasticsearchResponse<DynamicDictionary>> UpdateAsync(string index, string type, string id, object body, Func<UpdateRequestParameters, UpdateRequestParameters> requestParameters = null);
2008220082

20083-
/// <summary>
20084-
/// Perform any request you want over the configured IConnection synchronously while taking advantage of the cluster failover.
20085-
/// </summary>
20086-
/// <typeparam name="T">The type representing the response JSON</typeparam>
20087-
/// <param name="method">the HTTP Method to use</param>
20088-
/// <param name="path">The path of the the url that you would like to hit</param>
20089-
/// <param name="data">The body of the request, string and byte[] are posted as is other types will be serialized to JSON</param>
20090-
/// <param name="requestParameters">Optionally configure request specific timeouts, headers</param>
20091-
/// <returns>An ElasticsearchResponse of T where T represents the JSON response body</returns>
20092-
ElasticsearchResponse<T> DoRequest<T>(string method, string path, object data = null, IRequestParameters requestParameters = null);
20093-
20094-
/// <summary>
20095-
/// Perform any request you want over the configured IConnection asynchronously while taking advantage of the cluster failover.
20096-
/// </summary>
20097-
/// <typeparam name="T">The type representing the response JSON</typeparam>
20098-
/// <param name="method">the HTTP Method to use</param>
20099-
/// <param name="path">The path of the the url that you would like to hit</param>
20100-
/// <param name="data">The body of the request, string and byte[] are posted as is other types will be serialized to JSON</param>
20101-
/// <param name="requestParameters">Optionally configure request specific timeouts, headers</param>
20102-
/// <returns>A task of ElasticsearchResponse of T where T represents the JSON response body</returns>
20103-
Task<ElasticsearchResponse<T>> DoRequestAsync<T>(string method, string path, object data = null, IRequestParameters requestParameters = null);
2010420083
}
2010520084
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Elasticsearch.Net
8+
{
9+
public partial interface IElasticsearchClient
10+
{
11+
/// <summary>
12+
/// Perform any request you want over the configured IConnection synchronously while taking advantage of the cluster failover.
13+
/// </summary>
14+
/// <typeparam name="T">The type representing the response JSON</typeparam>
15+
/// <param name="method">the HTTP Method to use</param>
16+
/// <param name="path">The path of the the url that you would like to hit</param>
17+
/// <param name="data">The body of the request, string and byte[] are posted as is other types will be serialized to JSON</param>
18+
/// <param name="requestParameters">Optionally configure request specific timeouts, headers</param>
19+
/// <returns>An ElasticsearchResponse of T where T represents the JSON response body</returns>
20+
ElasticsearchResponse<T> DoRequest<T>(string method, string path, object data = null, IRequestParameters requestParameters = null);
21+
22+
/// <summary>
23+
/// Perform any request you want over the configured IConnection asynchronously while taking advantage of the cluster failover.
24+
/// </summary>
25+
/// <typeparam name="T">The type representing the response JSON</typeparam>
26+
/// <param name="method">the HTTP Method to use</param>
27+
/// <param name="path">The path of the the url that you would like to hit</param>
28+
/// <param name="data">The body of the request, string and byte[] are posted as is other types will be serialized to JSON</param>
29+
/// <param name="requestParameters">Optionally configure request specific timeouts, headers</param>
30+
/// <returns>A task of ElasticsearchResponse of T where T represents the JSON response body</returns>
31+
Task<ElasticsearchResponse<T>> DoRequestAsync<T>(string method, string path, object data = null, IRequestParameters requestParameters = null);
32+
33+
}
34+
}

src/Nest/Domain/Responses/GetMappingResponse.cs

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,17 @@ namespace Nest
77
{
88
public interface IGetMappingResponse : IResponse
99
{
10+
Dictionary<string, IList<TypeMapping>> Mappings { get; }
1011
RootObjectMapping Mapping { get; }
1112
void Accept(IMappingVisitor visitor);
1213
}
1314

15+
public class TypeMapping
16+
{
17+
public string TypeName { get; internal set; }
18+
public RootObjectMapping Mapping { get; internal set; }
19+
}
20+
1421
internal class GetRootObjectMappingWrapping : Dictionary<string, Dictionary<string, Dictionary<string, RootObjectMapping>>>
1522
{
1623

@@ -21,31 +28,43 @@ public class GetMappingResponse : BaseResponse, IGetMappingResponse
2128
public GetMappingResponse()
2229
{
2330
this.IsValid = true;
31+
this.Mappings = new Dictionary<string, IList<TypeMapping>>();
2432
}
2533

34+
2635
internal GetMappingResponse(IElasticsearchResponse status, GetRootObjectMappingWrapping dict)
2736
{
37+
this.Mappings = new Dictionary<string, IList<TypeMapping>>();
2838
this.IsValid = status.Success && dict != null && dict.Count > 0;
2939
if (!this.IsValid) return;
30-
var firstNode = dict.First();
31-
if (!firstNode.Value.HasAny())
32-
return;
33-
var mappingNode = firstNode.Value["mappings"];
34-
if (mappingNode == null)
40+
foreach (var index in dict)
3541
{
36-
this.IsValid = false;
37-
return;
38-
}
39-
var mapping = mappingNode.First();
40-
if (mapping.Value == null)
41-
{
42-
this.IsValid = false;
43-
return;
42+
if (index.Value == null || !index.Value.ContainsKey("mappings"))
43+
continue;
44+
45+
var mappings = index.Value["mappings"];
46+
this.Mappings.Add(index.Key, new List<TypeMapping>());
47+
if (mappings == null) continue;
48+
foreach (var mapping in mappings)
49+
{
50+
if (mapping.Value == null) continue;
51+
var typeMapping = new TypeMapping
52+
{
53+
TypeName = mapping.Key,
54+
Mapping = mapping.Value
55+
};
56+
mapping.Value.Name = mapping.Key;
57+
this.Mappings[index.Key].Add(typeMapping);
58+
}
4459
}
45-
mapping.Value.Name = mapping.Key;
46-
this.Mapping = mapping.Value;
60+
61+
this.Mapping = this.Mappings.Where(kv=>kv.Value.HasAny(v=>v.Mapping != null))
62+
.SelectMany(kv=>kv.Value)
63+
.Select(tm=>tm.Mapping)
64+
.FirstOrDefault(t=>t != null);
4765
}
4866

67+
public Dictionary<string, IList<TypeMapping>> Mappings { get; internal set; }
4968
public RootObjectMapping Mapping { get; internal set; }
5069

5170
public void Accept(IMappingVisitor visitor)

src/Tests/Nest.Tests.Integration/Aggregations/SingleBucketAggregationTests.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Linq;
22
using FluentAssertions;
3+
using Nest.Tests.MockData;
34
using Nest.Tests.MockData.Domain;
45
using NUnit.Framework;
56

@@ -24,18 +25,19 @@ public void Missing()
2425

2526
[Test]
2627
public void Filter()
27-
{
28+
{
29+
var lookFor = NestTestData.Data.Select(p => p.Country).First();
2830
var results = this.Client.Search<ElasticsearchProject>(s=>s
2931
.Size(0)
3032
.Aggregations(a=>a
3133
.Filter("filtered_agg", m=>m
32-
.Filter(f=>f.Term(p=>p.Country, "Sweden"))
34+
.Filter(f=>f.Term(p=>p.Country, lookFor))
3335
)
3436
)
3537
);
3638
results.IsValid.Should().BeTrue();
3739
var filteredBucket = results.Aggs.Filter("filtered_agg");
38-
filteredBucket.DocCount.Should().BeGreaterThan(1);
40+
filteredBucket.DocCount.Should().BeGreaterThan(0);
3941
}
4042

4143
[Test]

src/Tests/Nest.Tests.Integration/Core/CountTests.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using FluentAssertions;
2+
using Nest.Tests.MockData;
23
using Nest.Tests.MockData.Domain;
34
using NUnit.Framework;
45
using System;
@@ -24,11 +25,12 @@ public void CountTest()
2425
[Test]
2526
public void CountWithQueryTest()
2627
{
28+
var lookFor = NestTestData.Data.Select(p => p.Country).First();
2729
var response = this.Client.Count<ElasticsearchProject>(c => c
2830
.Query(q => q
2931
.Match(m => m
3032
.OnField(p => p.Country)
31-
.Query("Sweden")
33+
.Query(lookFor)
3234
)
3335
)
3436
);

src/Tests/Nest.Tests.Integration/Core/Map/Mapping/MappingTransformTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public void SingleTransformTest()
3232
.Index(ElasticsearchConfiguration.DefaultIndex)
3333
);
3434

35-
getResult.Mapping.Transform.Count.Should().Be(1);
35+
getResult.Mapping.Transform.Count.Should().BeGreaterOrEqualTo(1);
3636
}
3737

3838
[Test]

src/Tests/Nest.Tests.Integration/Core/UpdateTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Linq;
2+
using FluentAssertions;
23
using Nest.Tests.MockData;
34
using NUnit.Framework;
45
using Nest.Tests.MockData.Domain;
@@ -41,7 +42,7 @@ public void TestUpdate_ObjectInitializer()
4142
Script = "ctx._source.loc += 10",
4243
});
4344
project = this.Client.Source<ElasticsearchProject>(s => s.Id(id));
44-
Assert.AreEqual(project.LOC, loc + 10);
45+
project.LOC.Should().Be(loc + 10);
4546
Assert.AreNotEqual(project.Version, "1");
4647
}
4748

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using FluentAssertions;
5+
using Nest.Tests.MockData.Domain;
6+
using NUnit.Framework;
7+
8+
namespace Nest.Tests.Integration.Mapping
9+
{
10+
[TestFixture]
11+
public class GetMultipleMappingTests : IntegrationTests
12+
{
13+
private void TestElasticsearchProjectMapping(RootObjectMapping typeMapping)
14+
{
15+
Assert.NotNull(typeMapping);
16+
Assert.AreEqual("string", typeMapping.Properties["content"].Type.Name);
17+
Assert.AreEqual("string", typeMapping.Properties["country"].Type.Name);
18+
Assert.AreEqual("double", typeMapping.Properties["doubleValue"].Type.Name);
19+
Assert.AreEqual("long", typeMapping.Properties["longValue"].Type.Name);
20+
Assert.AreEqual("boolean", typeMapping.Properties["boolValue"].Type.Name);
21+
Assert.AreEqual("integer", typeMapping.Properties["intValues"].Type.Name);
22+
Assert.AreEqual("float", typeMapping.Properties["floatValues"].Type.Name);
23+
Assert.AreEqual("string", typeMapping.Properties["name"].Type.Name);
24+
Assert.AreEqual("date", typeMapping.Properties["startedOn"].Type.Name);
25+
Assert.AreEqual("long", typeMapping.Properties["stupidIntIWantAsLong"].Type.Name);
26+
Assert.AreEqual("float", typeMapping.Properties["floatValue"].Type.Name);
27+
Assert.AreEqual("integer", typeMapping.Properties["id"].Type.Name);
28+
Assert.AreEqual("integer", typeMapping.Properties["loc"].Type.Name);
29+
Assert.AreEqual("geo_point", typeMapping.Properties["origin"].Type.Name);
30+
Assert.AreEqual("object", typeMapping.Properties["product"].Type.Name);
31+
32+
var productMapping = typeMapping.Properties["product"] as ObjectMapping;
33+
Assert.NotNull(productMapping);
34+
Assert.AreEqual("string", productMapping.Properties["name"].Type.Name);
35+
Assert.AreEqual("string", productMapping.Properties["id"].Type.Name);
36+
37+
var countryMapping = typeMapping.Properties["country"] as StringMapping;
38+
Assert.NotNull(countryMapping);
39+
Assert.AreEqual(FieldIndexOption.NotAnalyzed, countryMapping.Index);
40+
}
41+
42+
private void TestPersonMapping(RootObjectMapping typeMapping)
43+
{
44+
Assert.NotNull(typeMapping);
45+
Assert.AreEqual("string", typeMapping.Properties["email"].Type.Name);
46+
var firstNameMapping = typeMapping.Properties["email"] as StringMapping;
47+
firstNameMapping.Should().NotBeNull();
48+
firstNameMapping.Index.Should().Be(FieldIndexOption.NotAnalyzed);
49+
}
50+
51+
[Test]
52+
public void GetSameMappingFromTwoDifferentIndices()
53+
{
54+
var indices = new[]
55+
{
56+
ElasticsearchConfiguration.NewUniqueIndexName(),
57+
ElasticsearchConfiguration.NewUniqueIndexName()
58+
};
59+
60+
var x = this.Client.CreateIndex(indices.First(), s => s
61+
.AddMapping<ElasticsearchProject>(m => m.MapFromAttributes())
62+
);
63+
Assert.IsTrue(x.Acknowledged, x.ConnectionStatus.ToString());
64+
65+
x = this.Client.CreateIndex(indices.Last(), s => s
66+
.AddMapping<ElasticsearchProject>(m => m.MapFromAttributes())
67+
);
68+
Assert.IsTrue(x.Acknowledged, x.ConnectionStatus.ToString());
69+
70+
var response = this.Client.GetMapping<ElasticsearchProject>(i => i
71+
.Index(string.Join(",", indices))
72+
.Type("elasticsearchprojects")
73+
);
74+
response.Should().NotBeNull();
75+
response.Mappings.Should().NotBeEmpty()
76+
.And.HaveCount(2);
77+
foreach (var indexMapping in response.Mappings)
78+
{
79+
var indexName = indexMapping.Key;
80+
indices.Should().Contain(indexName);
81+
var mappings = indexMapping.Value;
82+
mappings.Should().NotBeEmpty().And.HaveCount(1);
83+
foreach (var mapping in mappings)
84+
{
85+
mapping.TypeName.Should().Be("elasticsearchprojects");
86+
TestElasticsearchProjectMapping(mapping.Mapping);
87+
}
88+
}
89+
90+
91+
}
92+
93+
[Test]
94+
public void GetDifferentMappingsFromMultipleIndices()
95+
{
96+
var indices = new[]
97+
{
98+
ElasticsearchConfiguration.NewUniqueIndexName(),
99+
ElasticsearchConfiguration.NewUniqueIndexName()
100+
};
101+
102+
var x = this.Client.CreateIndex(indices.First(), s => s
103+
.AddMapping<ElasticsearchProject>(m => m.MapFromAttributes())
104+
.AddMapping<Person>(m => m.MapFromAttributes())
105+
);
106+
Assert.IsTrue(x.Acknowledged, x.ConnectionStatus.ToString());
107+
108+
x = this.Client.CreateIndex(indices.Last(), s => s
109+
.AddMapping<ElasticsearchProject>(m => m.MapFromAttributes())
110+
.AddMapping<GeoLocation>(m => m.MapFromAttributes())
111+
);
112+
Assert.IsTrue(x.Acknowledged, x.ConnectionStatus.ToString());
113+
114+
var response = this.Client.GetMapping(new GetMappingRequest(string.Join(",", indices), "*"));
115+
response.Should().NotBeNull();
116+
response.Mappings.Should().NotBeEmpty()
117+
.And.HaveCount(2);
118+
foreach (var indexMapping in response.Mappings)
119+
{
120+
var indexName = indexMapping.Key;
121+
indices.Should().Contain(indexName);
122+
var mappings = indexMapping.Value;
123+
mappings.Should().NotBeEmpty().And.HaveCount(2);
124+
mappings.Should().Contain(m => m.TypeName == "elasticsearchprojects")
125+
.And.Contain(m=>m.TypeName == (indexName == indices.First() ? "person" : "geolocation"));
126+
foreach (var mapping in mappings)
127+
{
128+
switch (mapping.TypeName)
129+
{
130+
case "elasticsearchprojects":
131+
TestElasticsearchProjectMapping(mapping.Mapping);
132+
break;
133+
case "person":
134+
TestPersonMapping(mapping.Mapping);
135+
break;
136+
case "geolocation":
137+
break;
138+
default:
139+
Assert.Fail("Unexpected mapping found {0}", mapping.TypeName);
140+
break;
141+
}
142+
}
143+
}
144+
145+
146+
}
147+
148+
}
149+
}

0 commit comments

Comments
 (0)