diff --git a/src/Nest/Document/Multiple/Bulk/BulkRequest.cs b/src/Nest/Document/Multiple/Bulk/BulkRequest.cs index 135473c7a42..659b77cbc5b 100644 --- a/src/Nest/Document/Multiple/Bulk/BulkRequest.cs +++ b/src/Nest/Document/Multiple/Bulk/BulkRequest.cs @@ -23,8 +23,8 @@ public partial class BulkDescriptor private BulkDescriptor AddOperation(IBulkOperation operation) => Assign(a => a.Operations.AddIfNotNull(operation)); public BulkDescriptor Create(Func, IBulkCreateOperation> bulkCreateSelector) where T : class => - Assign(a => AddOperation(bulkCreateSelector?.Invoke(new BulkCreateDescriptor()))); - + Assign(a => AddOperation(bulkCreateSelector?.Invoke(new BulkCreateDescriptor()))); + /// /// CreateMany, convenience method to create many documents at once. /// @@ -34,8 +34,8 @@ public BulkDescriptor CreateMany(IEnumerable @objects, Func @objects.ForEach(o => AddOperation(bulkCreateSelector.InvokeOrDefault(new BulkCreateDescriptor().Document(o), o)))); public BulkDescriptor Index(Func, IBulkIndexOperation> bulkIndexSelector) where T : class => - Assign(a => AddOperation(bulkIndexSelector?.Invoke(new BulkIndexDescriptor()))); - + Assign(a => AddOperation(bulkIndexSelector?.Invoke(new BulkIndexDescriptor()))); + /// /// IndexMany, convenience method to pass many objects at once. /// @@ -48,32 +48,50 @@ public BulkDescriptor Delete(T obj, Func, IBulkDelete Assign(a => AddOperation(bulkDeleteSelector.InvokeOrDefault(new BulkDeleteDescriptor().Document(obj)))); public BulkDescriptor Delete(Func, IBulkDeleteOperation> bulkDeleteSelector) where T : class => - Assign(a => AddOperation(bulkDeleteSelector?.Invoke(new BulkDeleteDescriptor()))); - + Assign(a => AddOperation(bulkDeleteSelector?.Invoke(new BulkDeleteDescriptor()))); + /// /// DeleteMany, convenience method to delete many objects at once. /// /// the objects to delete /// A func called on each object to describe the individual delete operation public BulkDescriptor DeleteMany(IEnumerable @objects, Func, T, IBulkDeleteOperation> bulkDeleteSelector = null) where T : class => - Assign(a => @objects.ForEach(o => AddOperation(bulkDeleteSelector.InvokeOrDefault(new BulkDeleteDescriptor().Document(o), o)))); - + Assign(a => @objects.ForEach(o => AddOperation(bulkDeleteSelector.InvokeOrDefault(new BulkDeleteDescriptor().Document(o), o)))); + /// /// DeleteMany, convenience method to delete many objects at once. /// /// Enumerable of string ids to delete /// A func called on each ids to describe the individual delete operation - public BulkDescriptor DeleteMany(IEnumerable ids, Func, string, IBulkDeleteOperation> bulkDeleteSelector = null) where T : class=> - Assign(a => ids.ForEach(o => AddOperation(bulkDeleteSelector.InvokeOrDefault(new BulkDeleteDescriptor().Id(o), o)))); - + public BulkDescriptor DeleteMany(IEnumerable ids, Func, string, IBulkDeleteOperation> bulkDeleteSelector = null) where T : class => + Assign(a => ids.ForEach(o => AddOperation(bulkDeleteSelector.InvokeOrDefault(new BulkDeleteDescriptor().Id(o), o)))); + /// /// DeleteMany, convenience method to delete many objects at once. /// /// Enumerable of int ids to delete /// A func called on each ids to describe the individual delete operation public BulkDescriptor DeleteMany(IEnumerable ids, Func, long, IBulkDeleteOperation> bulkDeleteSelector = null) where T : class => - Assign(a => ids.ForEach(o => AddOperation(bulkDeleteSelector.InvokeOrDefault(new BulkDeleteDescriptor().Id(o), o)))); - + Assign(a => ids.ForEach(o => AddOperation(bulkDeleteSelector.InvokeOrDefault(new BulkDeleteDescriptor().Id(o), o)))); + + /// + /// Updatemany, convenience method to pass many objects at once to do multiple updates. + /// + /// the objects to update + /// An func called on each object to describe the individual update operation + public BulkDescriptor UpdateMany(IEnumerable @objects, Func, T, IBulkUpdateOperation> bulkUpdateSelector) where T : class => + Assign(a => @objects.ForEach(o => AddOperation(bulkUpdateSelector.InvokeOrDefault(new BulkUpdateDescriptor().IdFrom(o), o)))); + + /// + /// Updatemany, convenience method to pass many objects at once to do multiple updates. + /// + /// the objects to update + /// An func called on each object to describe the individual update operation + public BulkDescriptor UpdateMany(IEnumerable @objects, Func, T, IBulkUpdateOperation> bulkUpdateSelector) + where T : class + where TPartialDocument : class => + Assign(a => @objects.ForEach(o => AddOperation(bulkUpdateSelector.InvokeOrDefault(new BulkUpdateDescriptor().IdFrom(o), o)))); + public BulkDescriptor Update(Func, IBulkUpdateOperation> bulkUpdateSelector) where T : class => this.Update(bulkUpdateSelector); diff --git a/src/Tests/Document/Multiple/Bulk/BulkUpdateManyTests.cs b/src/Tests/Document/Multiple/Bulk/BulkUpdateManyTests.cs new file mode 100644 index 00000000000..a1b1a769fe6 --- /dev/null +++ b/src/Tests/Document/Multiple/Bulk/BulkUpdateManyTests.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Elasticsearch.Net; +using FluentAssertions; +using Nest; +using Tests.Framework; +using Tests.Framework.Integration; +using Tests.Framework.MockData; +using Xunit; + +namespace Tests.Document.Multiple.Bulk +{ + public class BulkUpdateManyTests : ApiTestBase + { + private List Updates = Project.Projects.Take(10).ToList(); + + public BulkUpdateManyTests(ReadOnlyCluster cluster, EndpointUsage usage) : base(cluster, usage) { } + protected override LazyResponses ClientUsage() => Calls( + fluent: (client, f) => client.Bulk(f), + fluentAsync: (client, f) => client.BulkAsync(f), + request: (client, r) => client.Bulk(r), + requestAsync: (client, r) => client.BulkAsync(r) + ); + + protected override HttpMethod HttpMethod => HttpMethod.POST; + protected override string UrlPath => $"/{CallIsolatedValue}/_bulk"; + + protected override bool SupportsDeserialization => false; + + protected override object ExpectJson => Updates.SelectMany(ProjectToBulkJson); + + private IEnumerable ProjectToBulkJson(Project p) + { + yield return new Dictionary { { "update", new { _type = "project", _id = p.Name } } }; + yield return new { script = new { inline = "_source.counter++" } }; + } + + protected override Func Fluent => d => d + .Index(CallIsolatedValue) + .UpdateMany(Updates, (b, u) => b.Script(s => s.Inline("_source.counter++"))); + + + protected override BulkRequest Initializer => new BulkRequest(CallIsolatedValue) + { + Operations = Updates + .Select(u=> new BulkUpdateOperation(u) { Script = new InlineScript("_source.counter++") }) + .ToList() + }; + } +} diff --git a/src/Tests/Tests.csproj b/src/Tests/Tests.csproj index 157ee8f88e2..817a14a8567 100644 --- a/src/Tests/Tests.csproj +++ b/src/Tests/Tests.csproj @@ -224,6 +224,7 @@ + diff --git a/src/Tests/tests.yaml b/src/Tests/tests.yaml index 9ade76f9385..e59abbf30ea 100644 --- a/src/Tests/tests.yaml +++ b/src/Tests/tests.yaml @@ -1,5 +1,5 @@ # mode either u (unit test), i (integration test) or m (mixed mode) -mode: m +mode: u # the elasticsearch version that should be started # Can be a snapshot version of sonatype or "latest" to get the latest snapshot of sonatype elasticsearch_version: 5.0.1