Skip to content

Commit 2beb858

Browse files
adding bulkinsert support (#246)
add overload for Insert method to support bulk insert
1 parent 557123e commit 2beb858

File tree

3 files changed

+101
-1
lines changed

3 files changed

+101
-1
lines changed

src/Redis.OM/Searching/IRedisCollection.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,5 +242,20 @@ public interface IRedisCollection<T> : IOrderedQueryable<T>, IAsyncEnumerable<T>
242242
/// <param name="ids">The Ids to look up.</param>
243243
/// <returns>A dictionary correlating the ids provided to the objects in Redis.</returns>
244244
Task<IDictionary<string, T?>> FindByIdsAsync(IEnumerable<string> ids);
245+
246+
/// <summary>
247+
/// Inserts list of items into redis.
248+
/// </summary>
249+
/// <param name="items">The items to insert.</param>
250+
/// <returns>The list of Keys.</returns>
251+
Task<List<string>> Insert(IEnumerable<T> items);
252+
253+
/// <summary>
254+
/// Inserts list of items into redis.
255+
/// </summary>
256+
/// <param name="items">The items to insert.</param>
257+
/// <param name="timeSpan">The timespan of the document's (TTL).</param>
258+
/// /// <returns>The list of Keys.</returns>
259+
Task<List<string>> Insert(IEnumerable<T> items, TimeSpan timeSpan);
245260
}
246261
}

src/Redis.OM/Searching/RedisCollection.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,34 @@ public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToke
620620
return new RedisCollectionEnumerator<T>(Expression, provider.Connection, ChunkSize, StateManager, BooleanExpression, SaveState);
621621
}
622622

623+
/// <inheritdoc/>
624+
public async Task<List<string>> Insert(IEnumerable<T> items)
625+
{
626+
var tasks = new List<Task<string>>();
627+
foreach (var item in items.Distinct())
628+
{
629+
tasks.Add(((RedisQueryProvider)Provider).Connection.SetAsync(item));
630+
}
631+
632+
await Task.WhenAll(tasks);
633+
var result = tasks.Select(x => x.Result).ToList();
634+
return result;
635+
}
636+
637+
/// <inheritdoc/>
638+
public async Task<List<string>> Insert(IEnumerable<T> items, TimeSpan timeSpan)
639+
{
640+
var tasks = new List<Task<string>>();
641+
foreach (var item in items.Distinct())
642+
{
643+
tasks.Add(((RedisQueryProvider)Provider).Connection.SetAsync(item, timeSpan));
644+
}
645+
646+
await Task.WhenAll(tasks);
647+
var result = tasks.Select(x => x.Result).ToList();
648+
return result;
649+
}
650+
623651
private static MethodInfo GetMethodInfo<T1, T2>(Func<T1, T2> f, T1 unused)
624652
{
625653
return f.Method;

test/Redis.OM.Unit.Tests/RediSearchTests/SearchFunctionalTests.cs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -909,5 +909,62 @@ public async Task TestTimeStampRangesHash()
909909
CompareTimestamps(timestamp, first.NullableTimestamp.Value);
910910
Assert.Equal(obj.Id, first.Id);
911911
}
912+
913+
[Fact]
914+
public async Task TestBulkInsert()
915+
{
916+
var collection = new RedisCollection<Person>(_connection);
917+
var persons = new List<Person>() {
918+
new Person() { Name = "Alice", Age = 51, NickNames = new[] { "Ally", "Alie", "Al" }, },
919+
new Person() { Name = "Robert", Age = 37, NickNames = new[] { "Bobby", "Rob", "Bob" }, },
920+
new Person() { Name = "Jeeva", Age = 22, NickNames = new[] { "Jee", "Jeev", "J" }, },
921+
new Person() { Name = "Martin", Age = 60, NickNames = new[] { "Mart", "Mat", "tin" }, }
922+
};
923+
var keys = await collection.Insert(persons);
924+
var people = collection.Where(x => x.NickNames.Contains("Bob") || x.NickNames.Contains("Alie")).ToList();
925+
Assert.Contains(people, x => x.Name == persons.First().Name);
926+
}
927+
928+
[Fact]
929+
public async Task TestBulkInsertWithSameIds()
930+
{
931+
var collection = new RedisCollection<Person>(_connection);
932+
var persons = new List<Person>() {
933+
new Person() {Id="01GFZ9Y6CTEDHHXKT055N1YP3A" , Name = "Alice", Age = 51, NickNames = new[] { "Ally", "Alie", "Al" }, },
934+
new Person() {Id="01GFZ9Y6CTEDHHXKT055N1YP3A" , Name = "Robert", Age = 37, NickNames = new[] { "Bobby", "Rob", "Bob" }, },
935+
new Person() { Name = "Jeeva", Age = 22, NickNames = new[] { "Jee", "Jeev", "J" }, },
936+
new Person() { Name = "Martin", Age = 60, NickNames = new[] { "Mart", "Mat", "tin" }, }
937+
};
938+
await collection.Insert(persons);
939+
var people = await collection.Where(x => x.NickNames.Contains("Bob") || x.NickNames.Contains("Alie")).ToListAsync();
940+
Assert.Equal(people.Count, persons.Count - 3);
941+
Assert.False(people.First().Name == persons.First().Name); // this fails because the Name field of people doesn't contains the Name value Alice
942+
}
943+
944+
[Fact]
945+
public async Task BulkInsert50Records()
946+
{
947+
var collection = new RedisCollection<Person>(_connection);
948+
949+
var names = new[] { "Stever", "Martin", "Aegorn", "Robert", "Mary", "Joe", "Mark", "Otto" };
950+
var rand = new Random();
951+
var people = new List<Person>();
952+
for (var i = 0; i < 50; i++)
953+
{
954+
people.Add(new Person
955+
{
956+
Name = names[rand.Next(0, names.Length)],
957+
DepartmentNumber = rand.Next(1, 4),
958+
Sales = rand.Next(50000, 1000000),
959+
Age = rand.Next(17, 21),
960+
Height = 58.0 + rand.NextDouble() * 15,
961+
SalesAdjustment = rand.NextDouble()
962+
}
963+
);
964+
}
965+
await collection.Insert(people);
966+
var countPeople = collection.Where(x => x.Age >= 17 && x.Age <= 21).ToList().Count;
967+
Assert.Equal(people.Count, countPeople);
968+
}
912969
}
913-
}
970+
}

0 commit comments

Comments
 (0)