Skip to content

Commit c5809b7

Browse files
matteobortolazzo#171 - Support bulk delete
1 parent 9a2359c commit c5809b7

File tree

6 files changed

+119
-1
lines changed

6 files changed

+119
-1
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,8 @@ var list = await rebels.QueryAsync(someMangoJson);
277277
var list = await rebels.QueryAsync(someMangoObject);
278278
// Bulk
279279
await rebels.AddOrUpdateRangeAsync(moreRebels);
280+
await rebels.DeleteRangeAsync(ids);
281+
await rebels.DeleteRangeAsync(moreRebels);
280282
// Utils
281283
await rebels.CompactAsync();
282284
var info = await rebels.GetInfoAsync();

src/CouchDB.Driver/CouchDatabase.cs

+29
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,35 @@ await UpdateAttachments(document, cancellationToken)
319319
return documents;
320320
}
321321

322+
/// <inheritdoc />
323+
public Task DeleteRangeAsync(IEnumerable<TSource> documents, CancellationToken cancellationToken = default)
324+
{
325+
DocumentId[] docIds = documents.Cast<DocumentId>().ToArray();
326+
return DeleteRangeAsync(docIds, cancellationToken);
327+
}
328+
329+
/// <inheritdoc />
330+
public async Task DeleteRangeAsync(IEnumerable<DocumentId> documentIds, CancellationToken cancellationToken = default)
331+
{
332+
Check.NotNull(documentIds, nameof(documentIds));
333+
334+
var documents = documentIds
335+
.Select(docId => new
336+
{
337+
_id = docId.Id,
338+
_rev = docId.Rev,
339+
_deleted = true
340+
})
341+
.ToArray();
342+
343+
await NewRequest()
344+
.AppendPathSegment("_bulk_docs")
345+
.PostJsonAsync(new { docs = documents }, cancellationToken)
346+
.ReceiveJson<DocumentSaveResponse[]>()
347+
.SendRequestAsync()
348+
.ConfigureAwait(false);
349+
}
350+
322351
/// <inheritdoc />
323352
public async Task EnsureFullCommitAsync(CancellationToken cancellationToken = default)
324353
{

src/CouchDB.Driver/ICouchDatabase.cs

+16
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,22 @@ public interface ICouchDatabase<TSource>: IOrderedQueryable<TSource>
118118
/// <returns>A task that represents the asynchronous operation. The task result contains the elements created or updated.</returns>
119119
Task<IEnumerable<TSource>> AddOrUpdateRangeAsync(IList<TSource> documents, CancellationToken cancellationToken = default);
120120

121+
/// <summary>
122+
/// Delete multiple documents based on their ID and revision.
123+
/// </summary>
124+
/// <param name="documents">The documents to delete.</param>
125+
/// <param name="cancellationToken"> <see cref="CancellationToken" /> to observe while waiting for the task to complete.</param>
126+
/// <returns>A task that represents the asynchronous operation.</returns>
127+
Task DeleteRangeAsync(IEnumerable<TSource> documents, CancellationToken cancellationToken = default);
128+
129+
/// <summary>
130+
/// Delete multiple documents based on their ID and revision.
131+
/// </summary>
132+
/// <param name="documentIds">Documents to delete</param>
133+
/// <param name="cancellationToken"> <see cref="CancellationToken" /> to observe while waiting for the task to complete.</param>
134+
/// <returns>A task that represents the asynchronous operation.</returns>
135+
Task DeleteRangeAsync(IEnumerable<DocumentId> documentIds, CancellationToken cancellationToken = default);
136+
121137
/// <summary>
122138
/// Executes the specified view function from the specified design document.
123139
/// </summary>
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using CouchDB.Driver.Types;
2+
3+
namespace CouchDB.Driver;
4+
5+
public class DocumentId
6+
{
7+
public DocumentId(string id, string rev)
8+
{
9+
Id = id;
10+
Rev = rev;
11+
}
12+
13+
public DocumentId(CouchDocument document)
14+
{
15+
Id = document.Id;
16+
Rev = document.Rev;
17+
}
18+
19+
public string Id { get; }
20+
public string Rev { get; }
21+
22+
public static implicit operator DocumentId(CouchDocument documentId)
23+
{
24+
return new DocumentId(documentId.Id, documentId.Rev);
25+
}
26+
}

src/azure-pipelines.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
variables:
22
BuildConfiguration: Release
3-
PackageVersion: '3.2.0'
3+
PackageVersion: '3.3.0'
44

55
trigger:
66
branches:

tests/CouchDB.Driver.UnitTests/Database_Tests.cs

+45
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Flurl.Http.Testing;
44
using System;
55
using System.Collections.Generic;
6+
using System.Linq;
67
using System.Net.Http;
78
using System.Threading.Tasks;
89
using CouchDB.Driver.Extensions;
@@ -357,6 +358,50 @@ public async Task AddOrUpdateRange()
357358
.ShouldHaveCalled("http://localhost/rebels/_bulk_docs")
358359
.WithVerb(HttpMethod.Post);
359360
}
361+
362+
[Fact]
363+
public async Task DeleteRange()
364+
{
365+
using var httpTest = new HttpTest();
366+
// Response
367+
httpTest.RespondWithJson(new[] {
368+
new { Id = "111", Ok = true, Rev = "111" },
369+
new { Id = "222", Ok = true, Rev = "222" },
370+
});
371+
// Logout
372+
httpTest.RespondWithJson(new { ok = true });
373+
374+
var moreRebels = new[] {
375+
new Rebel { Name = "Luke", Id = "1" },
376+
new Rebel { Name = "Leia", Id = "2" }
377+
}.Cast<DocumentId>().ToArray();
378+
await _rebels.DeleteRangeAsync(moreRebels);
379+
httpTest
380+
.ShouldHaveCalled("http://localhost/rebels/_bulk_docs")
381+
.WithVerb(HttpMethod.Post);
382+
}
383+
384+
[Fact]
385+
public async Task DeleteRange_Docs()
386+
{
387+
using var httpTest = new HttpTest();
388+
// Response
389+
httpTest.RespondWithJson(new[] {
390+
new { Id = "111", Ok = true, Rev = "111" },
391+
new { Id = "222", Ok = true, Rev = "222" },
392+
});
393+
// Logout
394+
httpTest.RespondWithJson(new { ok = true });
395+
396+
var moreRebels = new[] {
397+
new Rebel { Name = "Luke", Id = "1" },
398+
new Rebel { Name = "Leia", Id = "2" }
399+
};
400+
await _rebels.DeleteRangeAsync(moreRebels);
401+
httpTest
402+
.ShouldHaveCalled("http://localhost/rebels/_bulk_docs")
403+
.WithVerb(HttpMethod.Post);
404+
}
360405

361406
#endregion
362407

0 commit comments

Comments
 (0)