diff --git a/IntegrationTests/GroupTests/GroupingTests.cs b/IntegrationTests/GroupTests/GroupingTests.cs new file mode 100644 index 0000000..751af45 --- /dev/null +++ b/IntegrationTests/GroupTests/GroupingTests.cs @@ -0,0 +1,108 @@ +using IntegrationTests.Infrastructure; +using MongoDbGenericRepository.Models; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace IntegrationTests.GroupTests +{ + public class GroupingTestsDocument : Document + { + public GroupingTestsDocument() + { + Version = 2; + Children = new List(); + } + public string SomeContent { get; set; } + public int GroupingKey { get; set; } + public List Children { get; set; } + } + + public class ProjectedGroup + { + public int Key { get; set; } + public List Content { get; set; } + } + + public class GroupingTests : BaseMongoDbRepositoryTests + { + [Test] + public void GroupByTProjection() + { + // Arrange + var documents = CreateTestDocuments(5); + for(var i = 0; i < documents.Count - 2; i++) + { + documents[i].GroupingKey = 1; + documents[i].SomeContent = $"content-{i}"; + } + for (var i = 3; i < documents.Count; i++) + { + documents[i].GroupingKey = 2; + documents[i].SomeContent = $"content-{i}"; + } + SUT.AddMany(documents); + + // Act + + var result = SUT.GroupBy( + e => e.GroupingKey, g => new ProjectedGroup { + Key = g.Key, + Content = g.Select(doc => doc.SomeContent).ToList() + }); + + // Assert + var key1Group = result.First(e => e.Key == 1); + Assert.NotNull(key1Group); + Assert.AreEqual(3, key1Group.Content.Count); + var key2Group = result.First(e => e.Key == 2); + Assert.NotNull(key2Group); + Assert.AreEqual(2, key2Group.Content.Count); + } + + [Test] + public void FilteredGroupByTProjection() + { + // Arrange + var documents = CreateTestDocuments(5); + for (var i = 0; i < documents.Count - 2; i++) + { + documents[i].GroupingKey = 4; + documents[i].SomeContent = $"content-{i}"; + } + for (var i = 3; i < documents.Count; i++) + { + documents[i].GroupingKey = 5; + documents[i].SomeContent = $"content-{i}"; + } + var guid1 = Guid.NewGuid().ToString("n"); + var guid2 = Guid.NewGuid().ToString("n"); + for (var i = 0; i < documents.Count - 1; i++) + { + documents[i].Children = new List { + new Child(guid1, guid2) + }; + } + + SUT.AddMany(documents); + + // Act + var result = SUT.GroupBy( + e => e.Children.Any(c => c.Type == guid1), + e => e.GroupingKey, g => new ProjectedGroup + { + Key = g.Key, + Content = g.Select(doc => doc.SomeContent).ToList() + }); + + // Assert + var key1Group = result.First(e => e.Key == 4); + Assert.NotNull(key1Group); + Assert.AreEqual(3, key1Group.Content.Count); + var key2Group = result.First(e => e.Key == 5); + Assert.NotNull(key2Group); + Assert.AreEqual(1, key2Group.Content.Count); + } + } +} diff --git a/IntegrationTests/Infrastructure/Child.cs b/IntegrationTests/Infrastructure/Child.cs new file mode 100644 index 0000000..cf9d1ec --- /dev/null +++ b/IntegrationTests/Infrastructure/Child.cs @@ -0,0 +1,14 @@ +namespace IntegrationTests.Infrastructure +{ + public class Child + { + public Child(string type, string value) + { + Type = type; + Value = value; + } + + public string Type { get; set; } + public string Value { get; set; } + } +} diff --git a/IntegrationTests/IntegrationTests.csproj b/IntegrationTests/IntegrationTests.csproj index f608e8b..d3bb63c 100644 --- a/IntegrationTests/IntegrationTests.csproj +++ b/IntegrationTests/IntegrationTests.csproj @@ -58,8 +58,10 @@ + + diff --git a/IntegrationTests/UpdatePartitionedTKeyTests.cs b/IntegrationTests/UpdatePartitionedTKeyTests.cs index 8cfb58a..41c66cf 100644 --- a/IntegrationTests/UpdatePartitionedTKeyTests.cs +++ b/IntegrationTests/UpdatePartitionedTKeyTests.cs @@ -1,8 +1,10 @@ using IntegrationTests.Infrastructure; using MongoDB.Bson.Serialization.Attributes; +using MongoDB.Driver; using MongoDbGenericRepository.Models; using NUnit.Framework; using System; +using System.Collections.Generic; using System.Threading.Tasks; namespace IntegrationTests @@ -18,9 +20,11 @@ namespace IntegrationTests Id = Guid.NewGuid(); Version = 2; PartitionKey = "TestPartitionKey"; + Children = new List(); } public string PartitionKey { get; set; } public string SomeContent { get; set; } + public List Children { get; set; } } [TestFixture] @@ -57,5 +61,57 @@ namespace IntegrationTests Assert.IsNotNull(updatedDocument); Assert.AreEqual("UpdateOneAsyncContent", updatedDocument.SomeContent); } + + [Test] + public async Task UpdateOneAsyncWithUpdateDefinition() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + var updateDef = Builders.Update.AddToSetEach(p => p.Children, childrenToAdd); + + // Act + var result = await SUT.UpdateOneAsync(document, updateDef); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id, document.PartitionKey); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } + + [Test] + public void UpdateOneWithUpdateDefinition() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + var updateDef = Builders.Update.AddToSetEach(p => p.Children, childrenToAdd); + + // Act + var result = SUT.UpdateOne(document, updateDef); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id, document.PartitionKey); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } } } diff --git a/IntegrationTests/UpdatePartitionedTests.cs b/IntegrationTests/UpdatePartitionedTests.cs index 3c0fa8a..fd7e3f9 100644 --- a/IntegrationTests/UpdatePartitionedTests.cs +++ b/IntegrationTests/UpdatePartitionedTests.cs @@ -1,6 +1,8 @@ using IntegrationTests.Infrastructure; +using MongoDB.Driver; using MongoDbGenericRepository.Models; using NUnit.Framework; +using System.Collections.Generic; using System.Threading.Tasks; namespace IntegrationTests @@ -10,8 +12,10 @@ namespace IntegrationTests public UpdateTestsPartitionedDocument() : base("TestPartitionKey") { Version = 2; + Children = new List(); } public string SomeContent { get; set; } + public List Children { get; set; } } public class UpdatePartitionedTests : BaseMongoDbRepositoryTests @@ -47,5 +51,155 @@ namespace IntegrationTests Assert.IsNotNull(updatedDocument); Assert.AreEqual("UpdateOneAsyncContent", updatedDocument.SomeContent); } + + [Test] + public async Task UpdateOneAsyncWithUpdateDefinition() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + var updateDef = Builders.Update.AddToSetEach(p => p.Children, childrenToAdd); + + // Act + var result = await SUT.UpdateOneAsync(document, updateDef); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id, document.PartitionKey); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } + + [Test] + public void UpdateOneWithUpdateDefinition() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + var updateDef = Builders.Update.AddToSetEach(p => p.Children, childrenToAdd); + + // Act + var result = SUT.UpdateOne(document, updateDef); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id, document.PartitionKey); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } + + [Test] + public void UpdateOneWithFieldSelector() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + // Act + var result = SUT.UpdateOne(document, x => x.Children, childrenToAdd); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id, document.PartitionKey); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } + + [Test] + public async Task UpdateOneAsyncWithFieldSelector() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + // Act + var result = await SUT.UpdateOneAsync(document, x => x.Children, childrenToAdd); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id, document.PartitionKey); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } + + [Test] + public void UpdateOneWithFilterAndFieldSelector() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + // Act + var filter = Builders.Filter.Eq("Id", document.Id); + var result = SUT.UpdateOne(filter, x => x.Children, childrenToAdd, document.PartitionKey); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id, document.PartitionKey); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } + + [Test] + public async Task UpdateOneAsyncWithFilterAndFieldSelector() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + // Act + var filter = Builders.Filter.Eq("Id", document.Id); + var result = await SUT.UpdateOneAsync(filter, x => x.Children, childrenToAdd, document.PartitionKey); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id, document.PartitionKey); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } } } diff --git a/IntegrationTests/UpdateTKeyTests.cs b/IntegrationTests/UpdateTKeyTests.cs index bcb77aa..f981196 100644 --- a/IntegrationTests/UpdateTKeyTests.cs +++ b/IntegrationTests/UpdateTKeyTests.cs @@ -1,8 +1,10 @@ using IntegrationTests.Infrastructure; using MongoDB.Bson.Serialization.Attributes; +using MongoDB.Driver; using MongoDbGenericRepository.Models; using NUnit.Framework; using System; +using System.Collections.Generic; using System.Threading.Tasks; namespace IntegrationTests @@ -17,8 +19,10 @@ namespace IntegrationTests { Id = Guid.NewGuid(); Version = 2; + Children = new List(); } public string SomeContent { get; set; } + public List Children { get; set; } } [TestFixture] @@ -55,5 +59,137 @@ namespace IntegrationTests Assert.IsNotNull(updatedDocument); Assert.AreEqual("UpdateOneAsyncContent", updatedDocument.SomeContent); } + + [Test] + public async Task UpdateOneAsyncWithUpdateDefinition() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + var updateDef = Builders.Update.AddToSetEach(p => p.Children, childrenToAdd); + // Act + var result = await SUT.UpdateOneAsync(document, updateDef); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } + + [Test] + public void UpdateOneWithUpdateDefinition() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + var updateDef = Builders.Update.AddToSetEach(p => p.Children, childrenToAdd); + + // Act + var result = SUT.UpdateOne(document, updateDef); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } + + [Test] + public void UpdateOneWithFieldSelector() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + var filter = Builders.Filter.Eq("Id", document.Id); + + // Act + var result = SUT.UpdateOne>(document, x => x.Children, childrenToAdd); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } + + [Test] + public async Task UpdateOneAsyncWithFieldSelector() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + var filter = Builders.Filter.Eq("Id", document.Id); + + // Act + var result = await SUT.UpdateOneAsync>(document, x => x.Children, childrenToAdd); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } + + [Test] + public void UpdateOneWithFilterAndFieldSelector() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + var filter = Builders.Filter.Eq("Id", document.Id); + + // Act + var result = SUT.UpdateOne>(filter, x => x.Children, childrenToAdd); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } } } diff --git a/IntegrationTests/UpdateTests.cs b/IntegrationTests/UpdateTests.cs index 328c3f3..ee5bb17 100644 --- a/IntegrationTests/UpdateTests.cs +++ b/IntegrationTests/UpdateTests.cs @@ -1,6 +1,8 @@ using IntegrationTests.Infrastructure; +using MongoDB.Driver; using MongoDbGenericRepository.Models; using NUnit.Framework; +using System.Collections.Generic; using System.Threading.Tasks; namespace IntegrationTests @@ -10,8 +12,10 @@ namespace IntegrationTests public UpdateTestsDocument() { Version = 2; + Children = new List(); } public string SomeContent { get; set; } + public List Children { get; set; } } public class UpdateTests : BaseMongoDbRepositoryTests @@ -47,5 +51,155 @@ namespace IntegrationTests Assert.IsNotNull(updatedDocument); Assert.AreEqual("UpdateOneAsyncContent", updatedDocument.SomeContent); } + + [Test] + public async Task UpdateOneAsyncWithUpdateDefinition() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + var updateDef = Builders.Update.AddToSetEach(p => p.Children, childrenToAdd); + + // Act + var result = await SUT.UpdateOneAsync(document, updateDef); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } + + [Test] + public void UpdateOneWithUpdateDefinition() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + var updateDef = Builders.Update.AddToSetEach(p => p.Children, childrenToAdd); + + // Act + var result = SUT.UpdateOne(document, updateDef); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } + + [Test] + public void UpdateOneWithFieldSelector() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + // Act + var result = SUT.UpdateOne(document, x => x.Children, childrenToAdd); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } + + [Test] + public async Task UpdateOneAsyncWithFieldSelector() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + // Act + var result = await SUT.UpdateOneAsync(document, x => x.Children, childrenToAdd); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } + + [Test] + public void UpdateOneWithFilterAndFieldSelector() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + // Act + var filter = Builders.Filter.Eq("Id", document.Id); + var result = SUT.UpdateOne(filter, x => x.Children, childrenToAdd); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } + + [Test] + public async Task UpdateOneAsyncWithFilterAndFieldSelector() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + var childrenToAdd = new List + { + new Child("testType1", "testValue1"), + new Child("testType2", "testValue2") + }; + + // Act + var filter = Builders.Filter.Eq("Id", document.Id); + var result = await SUT.UpdateOneAsync(filter, x => x.Children, childrenToAdd); + // Assert + Assert.IsTrue(result); + var updatedDocument = SUT.GetById(document.Id); + Assert.IsNotNull(updatedDocument); + Assert.AreEqual(childrenToAdd[0].Type, updatedDocument.Children[0].Type); + Assert.AreEqual(childrenToAdd[0].Value, updatedDocument.Children[0].Value); + Assert.AreEqual(childrenToAdd[1].Type, updatedDocument.Children[1].Type); + Assert.AreEqual(childrenToAdd[1].Value, updatedDocument.Children[1].Value); + } } } diff --git a/MongoDbGenericRepository/BaseMongoDbRepository.cs b/MongoDbGenericRepository/BaseMongoDbRepository.cs index 630a535..2b318ab 100644 --- a/MongoDbGenericRepository/BaseMongoDbRepository.cs +++ b/MongoDbGenericRepository/BaseMongoDbRepository.cs @@ -206,7 +206,7 @@ namespace MongoDbGenericRepository /// The type of the primary key for a Document. /// The Id of the document you want to get. /// An optional partition key. - Task GetByIdAsync(Guid id, string partitionKey = null) + Task GetByIdAsync(TKey id, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable; @@ -217,7 +217,7 @@ namespace MongoDbGenericRepository /// The type of the primary key for a Document. /// The Id of the document you want to get. /// An optional partition key. - TDocument GetById(Guid id, string partitionKey = null) + TDocument GetById(TKey id, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable; @@ -324,7 +324,6 @@ namespace MongoDbGenericRepository #endregion - #region Update /// @@ -341,6 +340,68 @@ namespace MongoDbGenericRepository /// The document with the modifications you want to persist. bool UpdateOne(TDocument modifiedDocument) where TDocument : IDocument; + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + bool UpdateOne(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + Task UpdateOneAsync(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + bool UpdateOne(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument; + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + Task UpdateOneAsync(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument; + + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The document you want to modify. + /// The update definition for the document. + Task UpdateOneAsync(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument; + + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The document you want to modify. + /// The update definition for the document. + bool UpdateOne(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument; + #endregion #region Update TKey @@ -365,6 +426,80 @@ namespace MongoDbGenericRepository where TDocument : IDocument where TKey : IEquatable; + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to modify. + /// The update definition for the document. + Task UpdateOneAsync(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to modify. + /// The update definition for the document. + bool UpdateOne(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + Task UpdateOneAsync(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + bool UpdateOne(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + Task UpdateOneAsync(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + bool UpdateOne(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + #endregion #region Delete @@ -535,7 +670,6 @@ namespace MongoDbGenericRepository #endregion - #region Project /// @@ -692,6 +826,43 @@ namespace MongoDbGenericRepository where TDocument : IDocument where TKey : IEquatable; + #region Grouping + + /// + /// Groups a collection of documents given a grouping criteria, + /// and returns a list of projected documents. + /// + /// The type representing a Document. + /// The type of the grouping criteria. + /// The type of the projected group. + /// The grouping criteria. + /// The projected group result. + /// The partition key of your document, if any. + List GroupBy( + Expression> groupingCriteria, + Expression, TProjection>> groupProjection, + string partitionKey = null) + where TDocument : IDocument + where TProjection : class, new(); + + /// Groups filtered a collection of documents given a grouping criteria, + /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. + /// + /// The type representing a Document. + /// The type of the grouping criteria. + /// The type of the projected group. + /// The grouping criteria. + /// The projected group result. + /// The partition key of your document, if any. + /// + List GroupBy(Expression> filter, + Expression> selector, + Expression, TProjection>> projection, + string partitionKey = null) + where TDocument : IDocument + where TProjection : class, new(); + + #endregion } /// @@ -1017,7 +1188,7 @@ namespace MongoDbGenericRepository /// The type of the primary key for a Document. /// The Id of the document you want to get. /// An optional partition key. - public async Task GetByIdAsync(Guid id, string partitionKey = null) + public async Task GetByIdAsync(TKey id, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { @@ -1032,7 +1203,7 @@ namespace MongoDbGenericRepository /// The type of the primary key for a Document. /// The Id of the document you want to get. /// An optional partition key. - public TDocument GetById(Guid id, string partitionKey = null) + public TDocument GetById(TKey id, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { @@ -1194,6 +1365,98 @@ namespace MongoDbGenericRepository return updateRes.ModifiedCount == 1; } + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The document you want to modify. + /// The update definition for the document. + public async Task UpdateOneAsync(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument + { + var filter = Builders.Filter.Eq("Id", documentToModify.Id); + var updateRes = await HandlePartitioned(documentToModify).UpdateOneAsync(filter, update); + return updateRes.ModifiedCount == 1; + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + public bool UpdateOne(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument + { + var filter = Builders.Filter.Eq("Id", documentToModify.Id); + var updateRes = HandlePartitioned(documentToModify).UpdateOne(filter, Builders.Update.Set(field, value)); + return updateRes.ModifiedCount == 1; + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + public async Task UpdateOneAsync(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument + { + var filter = Builders.Filter.Eq("Id", documentToModify.Id); + var updateRes = await HandlePartitioned(documentToModify).UpdateOneAsync(filter, Builders.Update.Set(field, value)); + return updateRes.ModifiedCount == 1; + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + public bool UpdateOne(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + { + var collection = string.IsNullOrEmpty(partitionKey) ? GetCollection() : GetCollection(partitionKey); + var updateRes = collection.UpdateOne(filter, Builders.Update.Set(field, value)); + return updateRes.ModifiedCount == 1; + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + public async Task UpdateOneAsync(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + { + var collection = string.IsNullOrEmpty(partitionKey) ? GetCollection() : GetCollection(partitionKey); + var updateRes = await collection.UpdateOneAsync(filter, Builders.Update.Set(field, value)); + return updateRes.ModifiedCount == 1; + } + + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The document you want to modify. + /// The update definition for the document. + public bool UpdateOne(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument + { + var filter = Builders.Filter.Eq("Id", documentToModify.Id); + var updateRes = HandlePartitioned(documentToModify).UpdateOne(filter, update, new UpdateOptions { IsUpsert = true }); + return updateRes.ModifiedCount == 1; + } + #endregion Update #region Update TKey @@ -1228,6 +1491,110 @@ namespace MongoDbGenericRepository return updateRes.ModifiedCount == 1; } + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to modify. + /// The update definition for the document. + public async Task UpdateOneAsync(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument + where TKey : IEquatable + { + var filter = Builders.Filter.Eq("Id", documentToModify.Id); + var updateRes = await HandlePartitioned(documentToModify).UpdateOneAsync(filter, update, new UpdateOptions { IsUpsert = true }); + return updateRes.ModifiedCount == 1; + } + + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to modify. + /// The update definition for the document. + public bool UpdateOne(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument + where TKey : IEquatable + { + var filter = Builders.Filter.Eq("Id", documentToModify.Id); + var updateRes = HandlePartitioned(documentToModify).UpdateOne(filter, update, new UpdateOptions { IsUpsert = true }); + return updateRes.ModifiedCount == 1; + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + public async Task UpdateOneAsync(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument + where TKey : IEquatable + { + var filter = Builders.Filter.Eq("Id", documentToModify.Id); + var updateRes = await HandlePartitioned(documentToModify).UpdateOneAsync(filter, Builders.Update.Set(field, value)); + return updateRes.ModifiedCount == 1; + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + public bool UpdateOne(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument + where TKey : IEquatable + { + var filter = Builders.Filter.Eq("Id", documentToModify.Id); + var updateRes = HandlePartitioned(documentToModify).UpdateOne(filter, Builders.Update.Set(field, value)); + return updateRes.ModifiedCount == 1; + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + public async Task UpdateOneAsync(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + var collection = string.IsNullOrEmpty(partitionKey) ? GetCollection() : GetCollection(partitionKey); + var updateRes = await collection.UpdateOneAsync(filter, Builders.Update.Set(field, value)); + return updateRes.ModifiedCount == 1; + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + public bool UpdateOne(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + var collection = string.IsNullOrEmpty(partitionKey) ? GetCollection() : GetCollection(partitionKey); + var updateRes = collection.UpdateOne(filter, Builders.Update.Set(field, value)); + return updateRes.ModifiedCount == 1; + } + #endregion Update #region Delete @@ -1601,7 +1968,7 @@ namespace MongoDbGenericRepository /// The type representing a Document. /// The type of the primary key for a Document. /// The type representing the model you want to project to. - /// + /// The document filter. /// The projection expression. /// An optional partition key. public List ProjectMany(Expression> filter, Expression> projection, string partitionKey = null) @@ -1614,6 +1981,60 @@ namespace MongoDbGenericRepository .ToList(); } + #endregion + + #region Grouping + + /// + /// Groups a collection of documents given a grouping criteria, + /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. + /// + /// The type representing a Document. + /// The type of the grouping criteria. + /// The type of the projected group. + /// The grouping criteria. + /// The projected group result. + /// The partition key of your document, if any. + public List GroupBy( + Expression> groupingCriteria, + Expression, TProjection>> groupProjection, + string partitionKey = null) + where TDocument : IDocument + where TProjection : class, new() + { + var collection = string.IsNullOrEmpty(partitionKey) ? GetCollection() : GetCollection(partitionKey); + return collection.Aggregate() + .Group(groupingCriteria, groupProjection) + .ToList(); + + } + + /// Groups filtered a collection of documents given a grouping criteria, + /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. + /// + /// The type representing a Document. + /// The type of the grouping criteria. + /// The type of the projected group. + /// The grouping criteria. + /// The projected group result. + /// The partition key of your document, if any. + /// + public List GroupBy(Expression> filter, + Expression> selector, + Expression, TProjection>> projection, + string partitionKey = null) + where TDocument : IDocument + where TProjection : class, new() + { + var collection = string.IsNullOrEmpty(partitionKey) ? GetCollection() : GetCollection(partitionKey); + + return collection.Aggregate() + .Match(Builders.Filter.Where(filter)) + .Group(selector, projection) + .ToList(); + } + + #endregion /// @@ -1732,7 +2153,6 @@ namespace MongoDbGenericRepository } } - private IMongoCollection GetCollection(string partitionKey) where TDocument : IDocument where TKey : IEquatable diff --git a/MongoDbGenericRepository/MongoDbGenericRepository.nuspec b/MongoDbGenericRepository/MongoDbGenericRepository.nuspec index 92ed6a0..2847dd6 100644 --- a/MongoDbGenericRepository/MongoDbGenericRepository.nuspec +++ b/MongoDbGenericRepository/MongoDbGenericRepository.nuspec @@ -2,7 +2,7 @@ MongoDbGenericRepository - 1.2.2 + 1.3 MongoDb Generic Repository Alexandre Spieser Alexandre Spieser diff --git a/MongoDbGenericRepository/lib/net45/MongoDbGenericRepository.xml b/MongoDbGenericRepository/lib/net45/MongoDbGenericRepository.xml index 618ae3f..9a99a51 100644 --- a/MongoDbGenericRepository/lib/net45/MongoDbGenericRepository.xml +++ b/MongoDbGenericRepository/lib/net45/MongoDbGenericRepository.xml @@ -174,7 +174,7 @@ A LINQ expression filter. An optional partition key. - + Asynchronously returns one document given its id. @@ -183,7 +183,7 @@ The Id of the document you want to get. An optional partition key. - + Returns one document given its id. @@ -287,6 +287,62 @@ The type representing a Document. The document with the modifications you want to persist. + + + Updates the property field with the given value update a property field in entities. + + The type representing a Document. + The type of the field. + The document filter. + The field selector. + The new value of the property field. + + + + Updates the property field with the given value update a property field in entities. + + The type representing a Document. + The type of the field. + The document filter. + The field selector. + The new value of the property field. + + + + Updates the property field with the given value update a property field in entities. + + The type representing a Document. + The type of the field. + The document you want to modify. + The field selector. + The new value of the property field. + + + + Updates the property field with the given value update a property field in entities. + + The type representing a Document. + The type of the field. + The document you want to modify. + The field selector. + The new value of the property field. + + + + Takes a document you want to modify and applies the update you have defined in MongoDb. + + The type representing a Document. + The document you want to modify. + The update definition for the document. + + + + Takes a document you want to modify and applies the update you have defined in MongoDb. + + The type representing a Document. + The document you want to modify. + The update definition for the document. + Asynchronously Updates a document. @@ -303,6 +359,68 @@ The type of the primary key for a Document. The document with the modifications you want to persist. + + + Takes a document you want to modify and applies the update you have defined in MongoDb. + + The type representing a Document. + The type of the primary key for a Document. + The document you want to modify. + The update definition for the document. + + + + Takes a document you want to modify and applies the update you have defined in MongoDb. + + The type representing a Document. + The type of the primary key for a Document. + The document you want to modify. + The update definition for the document. + + + + Updates the property field with the given value update a property field in entities. + + The type representing a Document. + The type of the primary key for a Document. + The type of the field. + The document you want to modify. + The field selector. + The new value of the property field. + + + + Updates the property field with the given value update a property field in entities. + + The type representing a Document. + The type of the primary key for a Document. + The type of the field. + The document you want to modify. + The field selector. + The new value of the property field. + + + + Updates the property field with the given value update a property field in entities. + + The type representing a Document. + The type of the primary key for a Document. + The type of the field. + The document filter. + The field selector. + The new value of the property field. + + + + Updates the property field with the given value update a property field in entities. + + The type representing a Document. + The type of the primary key for a Document. + The type of the field. + The document filter. + The field selector. + The new value of the property field. + Asynchronously deletes a document. @@ -573,6 +691,19 @@ + + + Groups a collection of documents given a grouping criteria, + and returns a list of projected documents. + + The type representing a Document. + The type of the grouping criteria. + The type of the projected group. + The grouping criteria. + The projected group result. + The partition key of your document, if any. + + The base Repository, it is meant to be inherited from by your custom custom MongoRepository implementation. @@ -763,7 +894,7 @@ A LINQ expression filter. An optional partitionKey - + Asynchronously returns one document given its id. @@ -772,7 +903,7 @@ The Id of the document you want to get. An optional partition key. - + Returns one document given its id. @@ -876,6 +1007,62 @@ The type representing a Document. The document with the modifications you want to persist. + + + Takes a document you want to modify and applies the update you have defined in MongoDb. + + The type representing a Document. + The document you want to modify. + The update definition for the document. + + + + Updates the property field with the given value update a property field in entities. + + The type representing a Document. + The type of the field. + The document you want to modify. + The field selector. + The new value of the property field. + + + + Updates the property field with the given value update a property field in entities. + + The type representing a Document. + The type of the field. + The document you want to modify. + The field selector. + The new value of the property field. + + + + Updates the property field with the given value update a property field in entities. + + The type representing a Document. + The type of the field. + The document filter. + The field selector. + The new value of the property field. + + + + Updates the property field with the given value update a property field in entities. + + The type representing a Document. + The type of the field. + The document filter. + The field selector. + The new value of the property field. + + + + Takes a document you want to modify and applies the update you have defined in MongoDb. + + The type representing a Document. + The document you want to modify. + The update definition for the document. + Asynchronously Updates a document. @@ -892,6 +1079,68 @@ The type of the primary key for a Document. The document with the modifications you want to persist. + + + Takes a document you want to modify and applies the update you have defined in MongoDb. + + The type representing a Document. + The type of the primary key for a Document. + The document you want to modify. + The update definition for the document. + + + + Takes a document you want to modify and applies the update you have defined in MongoDb. + + The type representing a Document. + The type of the primary key for a Document. + The document you want to modify. + The update definition for the document. + + + + Updates the property field with the given value update a property field in entities. + + The type representing a Document. + The type of the primary key for a Document. + The type of the field. + The document you want to modify. + The field selector. + The new value of the property field. + + + + Updates the property field with the given value update a property field in entities. + + The type representing a Document. + The type of the primary key for a Document. + The type of the field. + The document you want to modify. + The field selector. + The new value of the property field. + + + + Updates the property field with the given value update a property field in entities. + + The type representing a Document. + The type of the primary key for a Document. + The type of the field. + The document filter. + The field selector. + The new value of the property field. + + + + Updates the property field with the given value update a property field in entities. + + The type representing a Document. + The type of the primary key for a Document. + The type of the field. + The document filter. + The field selector. + The new value of the property field. + Asynchronously deletes a document. @@ -1116,10 +1365,23 @@ The type representing a Document. The type of the primary key for a Document. The type representing the model you want to project to. - + The document filter. The projection expression. An optional partition key. + + + Groups a collection of documents given a grouping criteria, + and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. + + The type representing a Document. + The type of the grouping criteria. + The type of the projected group. + The grouping criteria. + The projected group result. + The partition key of your document, if any. + + Asynchronously returns a paginated list of the documents matching the filter condition.