Skip to content

Commit c1461c1

Browse files
Bulk Operations Delete & Update (#278)
1 parent ff528ac commit c1461c1

File tree

5 files changed

+393
-100
lines changed

5 files changed

+393
-100
lines changed

src/Redis.OM/RedisCommands.cs

+16
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,14 @@ public static async Task<IDictionary<string, string>> HGetAllAsync(this IRedisCo
754754
/// <returns>the status.</returns>
755755
public static string Unlink(this IRedisConnection connection, string key) => connection.Execute("UNLINK", key);
756756

757+
/// <summary>
758+
/// Unlinks array of keys.
759+
/// </summary>
760+
/// <param name="connection">the connection.</param>
761+
/// <param name="keys">the keys to unlink.</param>
762+
/// <returns>the status.</returns>
763+
public static string Unlink(this IRedisConnection connection, string[] keys) => connection.Execute("UNLINK", keys);
764+
757765
/// <summary>
758766
/// Unlinks a key.
759767
/// </summary>
@@ -762,6 +770,14 @@ public static async Task<IDictionary<string, string>> HGetAllAsync(this IRedisCo
762770
/// <returns>the status.</returns>
763771
public static async Task<string> UnlinkAsync(this IRedisConnection connection, string key) => await connection.ExecuteAsync("UNLINK", key);
764772

773+
/// <summary>
774+
/// Unlinks array of keys.
775+
/// </summary>
776+
/// <param name="connection">the connection.</param>
777+
/// <param name="keys">the keys to unlink.</param>
778+
/// <returns>the status.</returns>
779+
public static async Task<string> UnlinkAsync(this IRedisConnection connection, string[] keys) => await connection.ExecuteAsync("UNLINK", keys);
780+
765781
/// <summary>
766782
/// Unlinks the key and then adds an updated value of it.
767783
/// </summary>

src/Redis.OM/Searching/IRedisCollection.cs

+35-15
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,21 @@ public interface IRedisCollection<T> : IOrderedQueryable<T>, IAsyncEnumerable<T>
8787
/// <returns>the Id of the newly inserted item, or null if not inserted.</returns>
8888
string? Insert(T item, WhenKey when, TimeSpan? timeSpan = null);
8989

90+
/// <summary>
91+
/// Inserts list of items into redis.
92+
/// </summary>
93+
/// <param name="items">The items to insert.</param>
94+
/// <returns>The list of Keys.</returns>
95+
Task<List<string>> Insert(IEnumerable<T> items);
96+
97+
/// <summary>
98+
/// Inserts list of items into redis.
99+
/// </summary>
100+
/// <param name="items">The items to insert.</param>
101+
/// <param name="timeSpan">The timespan of the document's (TTL).</param>
102+
/// /// <returns>The list of Keys.</returns>
103+
Task<List<string>> Insert(IEnumerable<T> items, TimeSpan timeSpan);
104+
90105
/// <summary>
91106
/// finds an item by it's ID or keyname.
92107
/// </summary>
@@ -127,19 +142,39 @@ public interface IRedisCollection<T> : IOrderedQueryable<T>, IAsyncEnumerable<T>
127142
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
128143
Task UpdateAsync(T item);
129144

145+
/// <summary>
146+
/// Updates the provided items in Redis. Document must have a property marked with the <see cref="RedisIdFieldAttribute"/>.
147+
/// </summary>
148+
/// <param name="items">The items to update.</param>
149+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
150+
ValueTask UpdateAsync(IEnumerable<T> items);
151+
130152
/// <summary>
131153
/// Deletes the item from Redis.
132154
/// </summary>
133155
/// <param name="item">The item to be deleted.</param>
134156
void Delete(T item);
135157

158+
/// <summary>
159+
/// Deletes the List of items from Redis.
160+
/// </summary>
161+
/// <param name="items">The items to be deleted.</param>
162+
void Delete(IEnumerable<T> items);
163+
136164
/// <summary>
137165
/// Deletes the item from Redis.
138166
/// </summary>
139167
/// <param name="item">The item to be deleted.</param>
140168
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
141169
Task DeleteAsync(T item);
142170

171+
/// <summary>
172+
/// Deletes the List of items from Redis.
173+
/// </summary>
174+
/// <param name="items">The items to be deleted.</param>
175+
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
176+
Task DeleteAsync(IEnumerable<T> items);
177+
143178
/// <summary>
144179
/// Async method for enumerating the collection to a list.
145180
/// </summary>
@@ -266,20 +301,5 @@ public interface IRedisCollection<T> : IOrderedQueryable<T>, IAsyncEnumerable<T>
266301
/// <param name="ids">The Ids to look up.</param>
267302
/// <returns>A dictionary correlating the ids provided to the objects in Redis.</returns>
268303
Task<IDictionary<string, T?>> FindByIdsAsync(IEnumerable<string> ids);
269-
270-
/// <summary>
271-
/// Inserts list of items into redis.
272-
/// </summary>
273-
/// <param name="items">The items to insert.</param>
274-
/// <returns>The list of Keys.</returns>
275-
Task<List<string>> Insert(IEnumerable<T> items);
276-
277-
/// <summary>
278-
/// Inserts list of items into redis.
279-
/// </summary>
280-
/// <param name="items">The items to insert.</param>
281-
/// <param name="timeSpan">The timespan of the document's (TTL).</param>
282-
/// /// <returns>The list of Keys.</returns>
283-
Task<List<string>> Insert(IEnumerable<T> items, TimeSpan timeSpan);
284304
}
285305
}

src/Redis.OM/Searching/RedisCollection.cs

+81-28
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Linq;
55
using System.Linq.Expressions;
66
using System.Reflection;
7+
using System.Text;
78
using System.Threading;
89
using System.Threading.Tasks;
910
using Redis.OM.Common;
@@ -191,6 +192,14 @@ public async Task UpdateAsync(T item)
191192
SaveToStateManager(key, item);
192193
}
193194

195+
/// <inheritdoc />
196+
public async ValueTask UpdateAsync(IEnumerable<T> items)
197+
{
198+
var tasks = items.Select(UpdateAsync);
199+
200+
await Task.WhenAll(tasks);
201+
}
202+
194203
/// <inheritdoc />
195204
public void Delete(T item)
196205
{
@@ -199,6 +208,23 @@ public void Delete(T item)
199208
StateManager.Remove(key);
200209
}
201210

211+
/// <inheritdoc />
212+
public void Delete(IEnumerable<T> items)
213+
{
214+
var keys = items.Select(x => x.GetKey()).ToArray();
215+
if (!keys.Any())
216+
{
217+
return;
218+
}
219+
220+
foreach (var key in keys)
221+
{
222+
StateManager.Remove(key);
223+
}
224+
225+
_connection.Unlink(keys);
226+
}
227+
202228
/// <inheritdoc />
203229
public async Task DeleteAsync(T item)
204230
{
@@ -207,6 +233,23 @@ public async Task DeleteAsync(T item)
207233
StateManager.Remove(key);
208234
}
209235

236+
/// <inheritdoc />
237+
public async Task DeleteAsync(IEnumerable<T> items)
238+
{
239+
var keys = items.Select(x => x.GetKey()).ToArray();
240+
if (!keys.Any())
241+
{
242+
return;
243+
}
244+
245+
foreach (var key in keys)
246+
{
247+
StateManager.Remove(key);
248+
}
249+
250+
await _connection.UnlinkAsync(keys);
251+
}
252+
210253
/// <inheritdoc />
211254
public async Task<IList<T>> ToListAsync()
212255
{
@@ -604,6 +647,44 @@ public async Task<string> InsertAsync(T item, TimeSpan timeSpan)
604647
return ((RedisQueryProvider)Provider).Connection.Set(item, when, timeSpan);
605648
}
606649

650+
/// <inheritdoc/>
651+
public async Task<List<string>> Insert(IEnumerable<T> items)
652+
{
653+
var distinct = items.Distinct().ToArray();
654+
if (!distinct.Any())
655+
{
656+
return new List<string>();
657+
}
658+
659+
var tasks = new List<Task<string>>();
660+
foreach (var item in distinct)
661+
{
662+
tasks.Add(((RedisQueryProvider)Provider).Connection.SetAsync(item));
663+
}
664+
665+
var result = await Task.WhenAll(tasks);
666+
return result.ToList();
667+
}
668+
669+
/// <inheritdoc/>
670+
public async Task<List<string>> Insert(IEnumerable<T> items, TimeSpan timeSpan)
671+
{
672+
var distinct = items.Distinct().ToArray();
673+
if (!distinct.Any())
674+
{
675+
return new List<string>();
676+
}
677+
678+
var tasks = new List<Task<string>>();
679+
foreach (var item in distinct)
680+
{
681+
tasks.Add(((RedisQueryProvider)Provider).Connection.SetAsync(item, timeSpan));
682+
}
683+
684+
var result = await Task.WhenAll(tasks);
685+
return result.ToList();
686+
}
687+
607688
/// <inheritdoc/>
608689
public T? FindById(string id)
609690
{
@@ -640,34 +721,6 @@ public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToke
640721
return new RedisCollectionEnumerator<T>(Expression, provider.Connection, ChunkSize, StateManager, BooleanExpression, SaveState);
641722
}
642723

643-
/// <inheritdoc/>
644-
public async Task<List<string>> Insert(IEnumerable<T> items)
645-
{
646-
var tasks = new List<Task<string>>();
647-
foreach (var item in items.Distinct())
648-
{
649-
tasks.Add(((RedisQueryProvider)Provider).Connection.SetAsync(item));
650-
}
651-
652-
await Task.WhenAll(tasks);
653-
var result = tasks.Select(x => x.Result).ToList();
654-
return result;
655-
}
656-
657-
/// <inheritdoc/>
658-
public async Task<List<string>> Insert(IEnumerable<T> items, TimeSpan timeSpan)
659-
{
660-
var tasks = new List<Task<string>>();
661-
foreach (var item in items.Distinct())
662-
{
663-
tasks.Add(((RedisQueryProvider)Provider).Connection.SetAsync(item, timeSpan));
664-
}
665-
666-
await Task.WhenAll(tasks);
667-
var result = tasks.Select(x => x.Result).ToList();
668-
return result;
669-
}
670-
671724
private static MethodInfo GetMethodInfo<T1, T2>(Func<T1, T2> f, T1 unused)
672725
{
673726
return f.Method;

0 commit comments

Comments
 (0)