Skip to content

Commit 827b9b6

Browse files
authored
fix #2389 add support for .UpdateMany() inside .Bulk() (#2433)
1 parent 14e8033 commit 827b9b6

File tree

4 files changed

+84
-14
lines changed

4 files changed

+84
-14
lines changed

src/Nest/Document/Multiple/Bulk/BulkRequest.cs

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ public partial class BulkDescriptor
2323
private BulkDescriptor AddOperation(IBulkOperation operation) => Assign(a => a.Operations.AddIfNotNull(operation));
2424

2525
public BulkDescriptor Create<T>(Func<BulkCreateDescriptor<T>, IBulkCreateOperation<T>> bulkCreateSelector) where T : class =>
26-
Assign(a => AddOperation(bulkCreateSelector?.Invoke(new BulkCreateDescriptor<T>())));
27-
26+
Assign(a => AddOperation(bulkCreateSelector?.Invoke(new BulkCreateDescriptor<T>())));
27+
2828
/// <summary>
2929
/// CreateMany, convenience method to create many documents at once.
3030
/// </summary>
@@ -34,8 +34,8 @@ public BulkDescriptor CreateMany<T>(IEnumerable<T> @objects, Func<BulkCreateDesc
3434
Assign(a => @objects.ForEach(o => AddOperation(bulkCreateSelector.InvokeOrDefault(new BulkCreateDescriptor<T>().Document(o), o))));
3535

3636
public BulkDescriptor Index<T>(Func<BulkIndexDescriptor<T>, IBulkIndexOperation<T>> bulkIndexSelector) where T : class =>
37-
Assign(a => AddOperation(bulkIndexSelector?.Invoke(new BulkIndexDescriptor<T>())));
38-
37+
Assign(a => AddOperation(bulkIndexSelector?.Invoke(new BulkIndexDescriptor<T>())));
38+
3939
/// <summary>
4040
/// IndexMany, convenience method to pass many objects at once.
4141
/// </summary>
@@ -48,32 +48,50 @@ public BulkDescriptor Delete<T>(T obj, Func<BulkDeleteDescriptor<T>, IBulkDelete
4848
Assign(a => AddOperation(bulkDeleteSelector.InvokeOrDefault(new BulkDeleteDescriptor<T>().Document(obj))));
4949

5050
public BulkDescriptor Delete<T>(Func<BulkDeleteDescriptor<T>, IBulkDeleteOperation<T>> bulkDeleteSelector) where T : class =>
51-
Assign(a => AddOperation(bulkDeleteSelector?.Invoke(new BulkDeleteDescriptor<T>())));
52-
51+
Assign(a => AddOperation(bulkDeleteSelector?.Invoke(new BulkDeleteDescriptor<T>())));
52+
5353
/// <summary>
5454
/// DeleteMany, convenience method to delete many objects at once.
5555
/// </summary>
5656
/// <param name="objects">the objects to delete</param>
5757
/// <param name="bulkDeleteSelector">A func called on each object to describe the individual delete operation</param>
5858
public BulkDescriptor DeleteMany<T>(IEnumerable<T> @objects, Func<BulkDeleteDescriptor<T>, T, IBulkDeleteOperation<T>> bulkDeleteSelector = null) where T : class =>
59-
Assign(a => @objects.ForEach(o => AddOperation(bulkDeleteSelector.InvokeOrDefault(new BulkDeleteDescriptor<T>().Document(o), o))));
60-
59+
Assign(a => @objects.ForEach(o => AddOperation(bulkDeleteSelector.InvokeOrDefault(new BulkDeleteDescriptor<T>().Document(o), o))));
60+
6161
/// <summary>
6262
/// DeleteMany, convenience method to delete many objects at once.
6363
/// </summary>
6464
/// <param name="ids">Enumerable of string ids to delete</param>
6565
/// <param name="bulkDeleteSelector">A func called on each ids to describe the individual delete operation</param>
66-
public BulkDescriptor DeleteMany<T>(IEnumerable<string> ids, Func<BulkDeleteDescriptor<T>, string, IBulkDeleteOperation<T>> bulkDeleteSelector = null) where T : class=>
67-
Assign(a => ids.ForEach(o => AddOperation(bulkDeleteSelector.InvokeOrDefault(new BulkDeleteDescriptor<T>().Id(o), o))));
68-
66+
public BulkDescriptor DeleteMany<T>(IEnumerable<string> ids, Func<BulkDeleteDescriptor<T>, string, IBulkDeleteOperation<T>> bulkDeleteSelector = null) where T : class =>
67+
Assign(a => ids.ForEach(o => AddOperation(bulkDeleteSelector.InvokeOrDefault(new BulkDeleteDescriptor<T>().Id(o), o))));
68+
6969
/// <summary>
7070
/// DeleteMany, convenience method to delete many objects at once.
7171
/// </summary>
7272
/// <param name="ids">Enumerable of int ids to delete</param>
7373
/// <param name="bulkDeleteSelector">A func called on each ids to describe the individual delete operation</param>
7474
public BulkDescriptor DeleteMany<T>(IEnumerable<long> ids, Func<BulkDeleteDescriptor<T>, long, IBulkDeleteOperation<T>> bulkDeleteSelector = null) where T : class =>
75-
Assign(a => ids.ForEach(o => AddOperation(bulkDeleteSelector.InvokeOrDefault(new BulkDeleteDescriptor<T>().Id(o), o))));
76-
75+
Assign(a => ids.ForEach(o => AddOperation(bulkDeleteSelector.InvokeOrDefault(new BulkDeleteDescriptor<T>().Id(o), o))));
76+
77+
/// <summary>
78+
/// Updatemany, convenience method to pass many objects at once to do multiple updates.
79+
/// </summary>
80+
/// <param name="objects">the objects to update</param>
81+
/// <param name="bulkUpdateSelector">An func called on each object to describe the individual update operation</param>
82+
public BulkDescriptor UpdateMany<T>(IEnumerable<T> @objects, Func<BulkUpdateDescriptor<T, T>, T, IBulkUpdateOperation<T, T>> bulkUpdateSelector) where T : class =>
83+
Assign(a => @objects.ForEach(o => AddOperation(bulkUpdateSelector.InvokeOrDefault(new BulkUpdateDescriptor<T, T>().IdFrom(o), o))));
84+
85+
/// <summary>
86+
/// Updatemany, convenience method to pass many objects at once to do multiple updates.
87+
/// </summary>
88+
/// <param name="objects">the objects to update</param>
89+
/// <param name="bulkUpdateSelector">An func called on each object to describe the individual update operation</param>
90+
public BulkDescriptor UpdateMany<T, TPartialDocument>(IEnumerable<T> @objects, Func<BulkUpdateDescriptor<T, TPartialDocument>, T, IBulkUpdateOperation<T, TPartialDocument>> bulkUpdateSelector)
91+
where T : class
92+
where TPartialDocument : class =>
93+
Assign(a => @objects.ForEach(o => AddOperation(bulkUpdateSelector.InvokeOrDefault(new BulkUpdateDescriptor<T, TPartialDocument>().IdFrom(o), o))));
94+
7795
public BulkDescriptor Update<T>(Func<BulkUpdateDescriptor<T, T>, IBulkUpdateOperation<T, T>> bulkUpdateSelector) where T : class =>
7896
this.Update<T, T>(bulkUpdateSelector);
7997

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Elasticsearch.Net;
5+
using FluentAssertions;
6+
using Nest;
7+
using Tests.Framework;
8+
using Tests.Framework.Integration;
9+
using Tests.Framework.MockData;
10+
using Xunit;
11+
12+
namespace Tests.Document.Multiple.Bulk
13+
{
14+
public class BulkUpdateManyTests : ApiTestBase<ReadOnlyCluster, IBulkResponse, IBulkRequest, BulkDescriptor, BulkRequest>
15+
{
16+
private List<Project> Updates = Project.Projects.Take(10).ToList();
17+
18+
public BulkUpdateManyTests(ReadOnlyCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
19+
protected override LazyResponses ClientUsage() => Calls(
20+
fluent: (client, f) => client.Bulk(f),
21+
fluentAsync: (client, f) => client.BulkAsync(f),
22+
request: (client, r) => client.Bulk(r),
23+
requestAsync: (client, r) => client.BulkAsync(r)
24+
);
25+
26+
protected override HttpMethod HttpMethod => HttpMethod.POST;
27+
protected override string UrlPath => $"/{CallIsolatedValue}/_bulk";
28+
29+
protected override bool SupportsDeserialization => false;
30+
31+
protected override object ExpectJson => Updates.SelectMany<Project, object>(ProjectToBulkJson);
32+
33+
private IEnumerable<object> ProjectToBulkJson(Project p)
34+
{
35+
yield return new Dictionary<string, object> { { "update", new { _type = "project", _id = p.Name } } };
36+
yield return new { script = new { inline = "_source.counter++" } };
37+
}
38+
39+
protected override Func<BulkDescriptor, IBulkRequest> Fluent => d => d
40+
.Index(CallIsolatedValue)
41+
.UpdateMany(Updates, (b, u) => b.Script(s => s.Inline("_source.counter++")));
42+
43+
44+
protected override BulkRequest Initializer => new BulkRequest(CallIsolatedValue)
45+
{
46+
Operations = Updates
47+
.Select(u=> new BulkUpdateOperation<Project, Project>(u) { Script = new InlineScript("_source.counter++") })
48+
.ToList<IBulkOperation>()
49+
};
50+
}
51+
}

src/Tests/Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@
224224
<Compile Include="Cluster\TaskManagement\GetTask\GetTaskApiTests.cs" />
225225
<Compile Include="Cluster\TaskManagement\GetTask\GetTaskUrlTests.cs" />
226226
<Compile Include="CodeStandards\Responses.doc.cs" />
227+
<Compile Include="Document\Multiple\Bulk\BulkUpdateManyTests.cs" />
227228
<Compile Include="Document\Multiple\Bulk\BulkInvalidVersionApiTests.cs" />
228229
<Compile Include="Document\Multiple\Bulk\BulkResponseParsingTests.cs" />
229230
<Compile Include="Document\Multiple\MultiGet\GetManyApiTests.cs" />

src/Tests/tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# mode either u (unit test), i (integration test) or m (mixed mode)
2-
mode: m
2+
mode: u
33
# the elasticsearch version that should be started
44
# Can be a snapshot version of sonatype or "latest" to get the latest snapshot of sonatype
55
elasticsearch_version: 5.0.1

0 commit comments

Comments
 (0)