From 0b939592ba2934ed1517adc3f9891ce2e42c2249 Mon Sep 17 00:00:00 2001 From: alexandre-spieser Date: Sun, 30 Sep 2018 19:07:38 +0100 Subject: [PATCH] Implementation of index management.CreateTextIndexWithOptionAsync is failing. --- .../CoreIntegrationTests.csproj | 5 +- .../Infrastructure/MongoDbDocumentTestBase.cs | 95 +++-- .../Abstractions/IBaseMongoRepository.cs | 2 +- .../BaseMongoDbRepository.IndexManagement.cs | 332 ++++++++++++++++++ .../BaseMongoDbRepository.cs | 231 +----------- MongoDbGenericRepository/MongoDbContext.cs | 24 +- 6 files changed, 422 insertions(+), 267 deletions(-) create mode 100644 MongoDbGenericRepository/BaseMongoDbRepository.IndexManagement.cs diff --git a/CoreIntegrationTests/CoreIntegrationTests.csproj b/CoreIntegrationTests/CoreIntegrationTests.csproj index 2a2e786..720179b 100644 --- a/CoreIntegrationTests/CoreIntegrationTests.csproj +++ b/CoreIntegrationTests/CoreIntegrationTests.csproj @@ -9,13 +9,16 @@ - + + + + ..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Configuration.dll diff --git a/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs b/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs index 2734c35..c1aa018 100644 --- a/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs +++ b/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs @@ -11,7 +11,7 @@ namespace CoreIntegrationTests.Infrastructure { public abstract class MongoDbDocumentTestBase : IClassFixture> - where T: TestDoc, new() + where T : TestDoc, new() { private readonly MongoDbTestFixture _fixture; @@ -73,7 +73,7 @@ namespace CoreIntegrationTests.Infrastructure // Act SUT.AddOne(document); // Assert - long count = string.IsNullOrEmpty(PartitionKey) ? SUT.Count(e => e.Id.Equals(document.Id)) + long count = string.IsNullOrEmpty(PartitionKey) ? SUT.Count(e => e.Id.Equals(document.Id)) : SUT.Count(e => e.Id.Equals(document.Id), PartitionKey); Assert.True(1 == count, GetTestName()); } @@ -88,7 +88,7 @@ namespace CoreIntegrationTests.Infrastructure // Assert long count = string.IsNullOrEmpty(PartitionKey) ? SUT.Count(e => e.Id.Equals(document.Id)) : SUT.Count(e => e.Id.Equals(document.Id), PartitionKey); - Assert.True (1 == count, GetTestName()); + Assert.True(1 == count, GetTestName()); } [Fact] @@ -103,7 +103,7 @@ namespace CoreIntegrationTests.Infrastructure || e.Id.Equals(documents[1].Id)) : SUT.Count(e => e.Id.Equals(documents[0].Id) || e.Id.Equals(documents[1].Id), PartitionKey); - Assert.True (2 == count, GetTestName()); + Assert.True(2 == count, GetTestName()); } [Fact] @@ -114,7 +114,7 @@ namespace CoreIntegrationTests.Infrastructure { // Arrange var documents = new List { new T(), new T(), new T(), new T() }; - if(documents.Any(e => e is IPartitionedDocument)) + if (documents.Any(e => e is IPartitionedDocument)) { var secondPartitionKey = $"{PartitionKey}-2"; ((IPartitionedDocument)documents[2]).PartitionKey = secondPartitionKey; @@ -144,7 +144,7 @@ namespace CoreIntegrationTests.Infrastructure || e.Id.Equals(documents[1].Id)) : SUT.Count(e => e.Id.Equals(documents[0].Id) || e.Id.Equals(documents[1].Id), PartitionKey); - Assert.True (2 == count, GetTestName()); + Assert.True(2 == count, GetTestName()); } [Fact] @@ -235,7 +235,7 @@ namespace CoreIntegrationTests.Infrastructure var cursor = SUT.GetCursor(x => x.Id.Equals(document.Id), PartitionKey); var count = cursor.Count(); // Assert - Assert.True (1 == count, GetTestName()); + Assert.True(1 == count, GetTestName()); } [Fact] @@ -490,10 +490,10 @@ namespace CoreIntegrationTests.Infrastructure Assert.True(result); var updatedDocument = SUT.GetById(document.Id, PartitionKey); Assert.True(null != updatedDocument); - Assert.True(childrenToAdd[0].Type== updatedDocument.Children[0].Type, GetTestName()); - Assert.True(childrenToAdd[0].Value== updatedDocument.Children[0].Value, GetTestName()); - Assert.True(childrenToAdd[1].Type== updatedDocument.Children[1].Type, GetTestName()); - Assert.True(childrenToAdd[1].Value== updatedDocument.Children[1].Value, GetTestName()); + Assert.True(childrenToAdd[0].Type == updatedDocument.Children[0].Type, GetTestName()); + Assert.True(childrenToAdd[0].Value == updatedDocument.Children[0].Value, GetTestName()); + Assert.True(childrenToAdd[1].Type == updatedDocument.Children[1].Type, GetTestName()); + Assert.True(childrenToAdd[1].Value == updatedDocument.Children[1].Value, GetTestName()); } #endregion Update @@ -509,7 +509,7 @@ namespace CoreIntegrationTests.Infrastructure // Act var result = SUT.DeleteOne(document); // Assert - Assert.True (1 == result); + Assert.True(1 == result); Assert.False(SUT.Any(e => e.Id.Equals(document.Id), PartitionKey), GetTestName()); } @@ -522,7 +522,7 @@ namespace CoreIntegrationTests.Infrastructure // Act var result = SUT.DeleteOne(e => e.Id.Equals(document.Id), PartitionKey); // Assert - Assert.True (1 == result); + Assert.True(1 == result); Assert.False(SUT.Any(e => e.Id.Equals(document.Id), PartitionKey), GetTestName()); } @@ -535,7 +535,7 @@ namespace CoreIntegrationTests.Infrastructure // Act var result = await SUT.DeleteOneAsync(document); // Assert - Assert.True (1 == result); + Assert.True(1 == result); Assert.False(SUT.Any(e => e.Id.Equals(document.Id), PartitionKey), GetTestName()); } @@ -548,7 +548,7 @@ namespace CoreIntegrationTests.Infrastructure // Act var result = await SUT.DeleteOneAsync(e => e.Id.Equals(document.Id), PartitionKey); // Assert - Assert.True (1 == result); + Assert.True(1 == result); Assert.False(SUT.Any(e => e.Id.Equals(document.Id), PartitionKey), GetTestName()); } @@ -765,7 +765,8 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; var documents = CreateTestDocuments(5); var i = 1; - documents.ForEach(e => { + documents.ForEach(e => + { e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); e.SomeContent = criteria; }); @@ -787,7 +788,8 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; var documents = CreateTestDocuments(5); var i = 1; - documents.ForEach(e => { + documents.ForEach(e => + { e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); e.SomeContent = criteria; }); @@ -809,7 +811,8 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; var documents = CreateTestDocuments(5); var i = 1; - documents.ForEach(e => { + documents.ForEach(e => + { e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); e.SomeContent = criteria; }); @@ -831,7 +834,8 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; var documents = CreateTestDocuments(5); var i = 1; - documents.ForEach(e => { + documents.ForEach(e => + { e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); e.SomeContent = criteria; }); @@ -853,7 +857,8 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; var documents = CreateTestDocuments(5); var i = 1; - documents.ForEach(e => { + documents.ForEach(e => + { e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); e.SomeContent = criteria; }); @@ -875,7 +880,8 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; var documents = CreateTestDocuments(5); var i = 1; - documents.ForEach(e => { + documents.ForEach(e => + { e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); e.SomeContent = criteria; }); @@ -897,7 +903,8 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; var documents = CreateTestDocuments(5); var i = 1; - documents.ForEach(e => { + documents.ForEach(e => + { e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); e.SomeContent = criteria; }); @@ -919,7 +926,8 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; var documents = CreateTestDocuments(5); var i = 1; - documents.ForEach(e => { + documents.ForEach(e => + { e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); e.SomeContent = criteria; }); @@ -936,6 +944,47 @@ namespace CoreIntegrationTests.Infrastructure #endregion Max / Min Queries + #region Index Management + + [Fact] + public async Task CreateTextIndexNoOptionAsync() + { + // Arrange + const string expectedIndexName = "SomeContent_text"; + + // Act + var result = await SUT.CreateTextIndexAsync(x => x.SomeContent, null, PartitionKey); + + // Assert + var listOfIndexNames = await SUT.GetIndexesNamesAsync(PartitionKey); + Assert.Contains(expectedIndexName, listOfIndexNames); + + // Cleanup + await SUT.DropIndexAsync(expectedIndexName, PartitionKey); + } + + [Fact] + public async Task CreateTextIndexWithOptionAsync() + { + // Arrange + string expectedIndexName = $"SomeContent_text_{Guid.NewGuid()}"; + var option = new IndexCreationOptions + { + Name = expectedIndexName + }; + // Act + var result = await SUT.CreateTextIndexAsync(x => x.SomeContent, option, PartitionKey); + + // Assert + var listOfIndexNames = await SUT.GetIndexesNamesAsync(PartitionKey); + Assert.Contains(expectedIndexName, listOfIndexNames); + + // Cleanup + await SUT.DropIndexAsync(expectedIndexName, PartitionKey); + } + + #endregion Index Management + #region Test Utils [MethodImpl(MethodImplOptions.NoInlining)] diff --git a/MongoDbGenericRepository/Abstractions/IBaseMongoRepository.cs b/MongoDbGenericRepository/Abstractions/IBaseMongoRepository.cs index b8a962d..64d9e99 100644 --- a/MongoDbGenericRepository/Abstractions/IBaseMongoRepository.cs +++ b/MongoDbGenericRepository/Abstractions/IBaseMongoRepository.cs @@ -12,7 +12,7 @@ namespace MongoDbGenericRepository /// /// The IBaseMongoRepository exposes the CRUD functionality of the BaseMongoRepository. /// - public interface IBaseMongoRepository : IReadOnlyMongoRepository + public interface IBaseMongoRepository : IReadOnlyMongoRepository, IMongoDbCollectionIndexRepository { #region Create diff --git a/MongoDbGenericRepository/BaseMongoDbRepository.IndexManagement.cs b/MongoDbGenericRepository/BaseMongoDbRepository.IndexManagement.cs new file mode 100644 index 0000000..b24394f --- /dev/null +++ b/MongoDbGenericRepository/BaseMongoDbRepository.IndexManagement.cs @@ -0,0 +1,332 @@ +using MongoDB.Driver; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq.Expressions; +using MongoDbGenericRepository.Models; +using System.Linq; + +namespace MongoDbGenericRepository +{ + /// + /// The repository interface for managing indexes + /// + public interface IMongoDbCollectionIndexRepository + { + /// + /// Create a text index on the given field. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The field we want to index + /// Options for creating an index.. + /// An optional partition key + /// The result of the create index operation. + Task CreateTextIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Create a text index on the given field. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The field we want to index + /// Options for creating an index.. + /// An optional partition key + /// The result of the create index operation. + Task CreateTextIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Creates an index on the given field in ascending order + /// + /// The type representing a Document. + /// The field we want to index + /// Options for creating an index.. + /// An optional partition key + /// The result of the create index operation. + Task CreateAscendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) where TDocument : IDocument; + + /// + /// Creates an index on the given field in ascending order + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The field we want to index + /// Options for creating an index.. + /// An optional partition key + /// The result of the create index operation. + Task CreateAscendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Creates an index on the given field in descending order + /// + /// The type representing a Document. + /// The field we want to index + /// Options for creating an index.. + /// An optional partition key + /// A string containing the result of the operation. + Task CreateDescendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Creates a hashed index on the given field. + /// + /// The type representing a Document. + /// The field we want to index + /// Options for creating an index.. + /// An optional partition key + /// A string containing the result of the operation. + Task CreateHashedIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Creates a hashed index on the given field. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The field we want to index + /// Options for creating an index.. + /// An optional partition key + /// The result of the create index operation. + Task CreateHashedIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Creates a combined text index + /// + /// The type representing a Document. + /// The fields we want to index + /// Options for creating an index.. + /// An optional partition key + /// The result of the create index operation. + Task CreateCombinedTextIndexAsync(IEnumerable>> fields, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Creates a combined text index + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The fields we want to index + /// Options for creating an index.. + /// An optional partition key + /// The result of the create index operation. + Task CreateCombinedTextIndexAsync(IEnumerable>> fields, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Drops the index given a field name + /// + /// The type representing a Document. + /// The name of the index + /// An optional partition key + Task DropIndexAsync(string indexName, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Drops the index given a field name + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The name of the index + /// An optional partition key + Task DropIndexAsync(string indexName, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Returns the names of the indexes present on a collection. + /// + /// The type representing a Document. + /// An optional partition key + /// A list containing the names of the indexes on on the concerned collection. + Task> GetIndexesNamesAsync(string partitionKey = null) + where TDocument : IDocument; + + /// + /// Returns the names of the indexes present on a collection. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// An optional partition key + /// A list containing the names of the indexes on on the concerned collection. + Task> GetIndexesNamesAsync(string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + } + + /// + /// The base Repository, it is meant to be inherited from by your custom custom MongoRepository implementation. + /// Its constructor must be given a connection string and a database name. + /// + public abstract partial class BaseMongoRepository : ReadOnlyMongoRepository, IBaseMongoRepository + { + #region Index Management + + /// + public async Task CreateTextIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + { + return await CreateTextIndexAsync(field, indexCreationOptions, partitionKey); + } + + /// + public async Task CreateTextIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await HandlePartitioned(partitionKey).Indexes + .CreateOneAsync( + new CreateIndexModel( + Builders.IndexKeys.Text(field), + indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions) + )); + } + + /// + public async Task CreateAscendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) where TDocument : IDocument + { + return await CreateAscendingIndexAsync(field, indexCreationOptions, partitionKey); + } + + /// + public async Task CreateAscendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + var collection = HandlePartitioned(partitionKey); + var createOptions = indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions); + var indexKey = Builders.IndexKeys; + return await collection.Indexes + .CreateOneAsync( + new CreateIndexModel(indexKey.Ascending(field), createOptions)); + } + + /// + public async Task CreateDescendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + { + return await CreateDescendingIndexAsync(field, indexCreationOptions, partitionKey); + } + + /// + public async Task CreateDescendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + var collection = HandlePartitioned(partitionKey); + var createOptions = indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions); + var indexKey = Builders.IndexKeys; + return await collection.Indexes + .CreateOneAsync( + new CreateIndexModel(indexKey.Descending(field), createOptions)); + } + + /// + public async Task CreateHashedIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + { + return await CreateHashedIndexAsync(field, indexCreationOptions, partitionKey); + } + + /// + public async Task CreateHashedIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + var collection = HandlePartitioned(partitionKey); + var createOptions = indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions); + var indexKey = Builders.IndexKeys; + return await collection.Indexes + .CreateOneAsync( + new CreateIndexModel(indexKey.Hashed(field), createOptions)); + } + + /// + public async Task CreateCombinedTextIndexAsync(IEnumerable>> fields, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) where TDocument : IDocument + { + return await CreateCombinedTextIndexAsync(fields, indexCreationOptions, partitionKey); + } + + /// + public async Task CreateCombinedTextIndexAsync(IEnumerable>> fields, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + var collection = HandlePartitioned(partitionKey); + var createOptions = indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions); + var listOfDefs = new List>(); + foreach (var field in fields) + { + listOfDefs.Add(Builders.IndexKeys.Text(field)); + } + return await collection.Indexes + .CreateOneAsync(new CreateIndexModel(Builders.IndexKeys.Combine(listOfDefs), createOptions)); + } + + /// + public async Task DropIndexAsync(string indexName, string partitionKey = null) + where TDocument : IDocument + { + await DropIndexAsync(indexName, partitionKey); + } + + /// + public async Task DropIndexAsync(string indexName, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + await HandlePartitioned(partitionKey).Indexes.DropOneAsync(indexName); + } + + /// + public async Task> GetIndexesNamesAsync(string partitionKey = null) + where TDocument : IDocument + { + return await GetIndexesNamesAsync(partitionKey); + } + + /// + public async Task> GetIndexesNamesAsync(string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + var indexCursor = await HandlePartitioned(partitionKey).Indexes.ListAsync(); + var indexes = await indexCursor.ToListAsync(); + return indexes.Select(e => e["name"].ToString()).ToList(); + } + + + #endregion Index Management + + private CreateIndexOptions MapIndexOptions(IndexCreationOptions indexCreationOptions) + { + return new CreateIndexOptions + { + Unique = indexCreationOptions.Unique, + TextIndexVersion = indexCreationOptions.TextIndexVersion, + SphereIndexVersion = indexCreationOptions.SphereIndexVersion, + Sparse = indexCreationOptions.Sparse, + Name = indexCreationOptions.Name, + Min = indexCreationOptions.Min, + Max = indexCreationOptions.Max, + LanguageOverride = indexCreationOptions.LanguageOverride, + ExpireAfter = indexCreationOptions.ExpireAfter, + DefaultLanguage = indexCreationOptions.DefaultLanguage, + BucketSize = indexCreationOptions.BucketSize, + Bits = indexCreationOptions.Bits, + Background = indexCreationOptions.Background, + Version = indexCreationOptions.Version + }; + } + } +} \ No newline at end of file diff --git a/MongoDbGenericRepository/BaseMongoDbRepository.cs b/MongoDbGenericRepository/BaseMongoDbRepository.cs index 138877f..7a3a76e 100644 --- a/MongoDbGenericRepository/BaseMongoDbRepository.cs +++ b/MongoDbGenericRepository/BaseMongoDbRepository.cs @@ -13,9 +13,8 @@ namespace MongoDbGenericRepository /// The base Repository, it is meant to be inherited from by your custom custom MongoRepository implementation. /// Its constructor must be given a connection string and a database name. /// - public abstract class BaseMongoRepository : ReadOnlyMongoRepository, IBaseMongoRepository + public abstract partial class BaseMongoRepository : ReadOnlyMongoRepository, IBaseMongoRepository { - /// /// The constructor taking a connection string and a database name. /// @@ -1081,234 +1080,6 @@ namespace MongoDbGenericRepository #endregion Find And Update - #region Index Management - - /// - /// Create an Index given a field and an optional ascending / descending parameter - /// we want to create them in the background as we want the db to still be available during this process - /// - /// The type representing a Document. - /// The field we want to index - /// Options for creating an index.. - /// An optional partition key - /// The result of the create index operation. - public async Task CreateTextIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - { - return await CreateTextIndexAsync(field, indexCreationOptions, partitionKey); - } - - /// - /// Create an Index given a field and an optional ascending / descending parameter - /// we want to create them in the background as we want the db to still be available during this process - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The field we want to index - /// Options for creating an index.. - /// An optional partition key - /// The result of the create index operation. - public async Task CreateTextIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await HandlePartitioned(partitionKey).Indexes - .CreateOneAsync( - new CreateIndexModel( - Builders.IndexKeys.Text(field), - indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions) - )); - } - - /// - /// Creates an index on the given field in ascending order - /// - /// The type representing a Document. - /// The field we want to index - /// Options for creating an index.. - /// An optional partition key - /// The result of the create index operation. - public async Task CreateAscendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) where TDocument : IDocument - { - return await CreateAscendingIndexAsync(field, indexCreationOptions, partitionKey); - } - - /// - /// Creates an index on the given field in ascending order - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The field we want to index - /// Options for creating an index.. - /// An optional partition key - /// The result of the create index operation. - public async Task CreateAscendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var collection = HandlePartitioned(partitionKey); - var createOptions = indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions); - var indexKey = Builders.IndexKeys; - return await collection.Indexes - .CreateOneAsync( - new CreateIndexModel(indexKey.Ascending(field), createOptions)); - } - - /// - /// Creates an index on the given field in ascending order - /// - /// The type representing a Document. - /// The field we want to index - /// Options for creating an index.. - /// An optional partition key - /// - public async Task CreateDescendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) where TDocument : IDocument - { - return await CreateDescendingIndexAsync(field, indexCreationOptions, partitionKey); - } - - /// - /// Creates an index on the given field in descending order - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The field we want to index - /// Options for creating an index.. - /// An optional partition key - /// The result of the create index operation. - public async Task CreateDescendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var collection = HandlePartitioned(partitionKey); - var createOptions = indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions); - var indexKey = Builders.IndexKeys; - return await collection.Indexes - .CreateOneAsync( - new CreateIndexModel(indexKey.Descending(field), createOptions)); - } - - /// - /// Create an Index given a field and an optional ascending / descending parameter - /// - /// The type representing a Document. - /// The field we want to index - /// Options for creating an index.. - /// An optional partition key - /// - public async Task CreateHashedIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) where TDocument : IDocument - { - return await CreateHashedIndexAsync(field, indexCreationOptions, partitionKey); - } - - /// - /// Creates a hashed index on the given field. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The field we want to index - /// Options for creating an index.. - /// An optional partition key - /// The result of the create index operation. - public async Task CreateHashedIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var collection = HandlePartitioned(partitionKey); - var createOptions = indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions); - var indexKey = Builders.IndexKeys; - return await collection.Indexes - .CreateOneAsync( - new CreateIndexModel(indexKey.Hashed(field), createOptions)); - } - - /// - /// Creates a combined text index - /// - /// The type representing a Document. - /// The fields we want to index - /// Options for creating an index.. - /// An optional partition key - /// The result of the create index operation. - public async Task CreateCombinedTextIndexAsync(IEnumerable>> fields, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) where TDocument : IDocument - { - return await CreateCombinedTextIndexAsync(fields, indexCreationOptions, partitionKey); - } - - /// - /// Creates a combined text index - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The fields we want to index - /// Options for creating an index.. - /// An optional partition key - /// The result of the create index operation. - public async Task CreateCombinedTextIndexAsync(IEnumerable>> fields, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var collection = HandlePartitioned(partitionKey); - var createOptions = indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions); - var listOfDefs = new List>(); - foreach (var field in fields) - { - listOfDefs.Add(Builders.IndexKeys.Text(field)); - } - return await collection.Indexes - .CreateOneAsync(new CreateIndexModel(Builders.IndexKeys.Combine(listOfDefs), createOptions)); - } - - /// - /// Drops the index given a field name - /// - /// - /// - /// - public async Task DropIndexAsync(string fieldName) where T : BaseMongoEntity - { - var collection = GetCollection(); - await collection.Indexes.DropOneAsync(fieldName); - } - - /// - /// Drops the index given a field name - /// - /// - /// - public async Task> GetIndexesNamesAsync() where T : BaseMongoEntity - { - var collection = GetCollection(); - var indexCursor = await collection.Indexes.ListAsync(); - var indexes = await indexCursor.ToListAsync(); - var values = indexes.Select(e => e["name"].ToString()).ToList(); - return values; - } - - - #endregion Index Management - - private CreateIndexOptions MapIndexOptions(IndexCreationOptions indexCreationOptions) - { - return new CreateIndexOptions - { - Unique = indexCreationOptions.Unique, - TextIndexVersion = indexCreationOptions.TextIndexVersion, - SphereIndexVersion = indexCreationOptions.SphereIndexVersion, - Sparse = indexCreationOptions.Sparse, - Name = indexCreationOptions.Name, - Min = indexCreationOptions.Min, - Max = indexCreationOptions.Max, - LanguageOverride = indexCreationOptions.LanguageOverride, - ExpireAfter = indexCreationOptions.ExpireAfter, - DefaultLanguage = indexCreationOptions.DefaultLanguage, - BucketSize = indexCreationOptions.BucketSize, - Bits = indexCreationOptions.Bits, - Background = indexCreationOptions.Background, - Version = indexCreationOptions.Version - }; - } - /// /// Sets the value of the document Id if it is not set already. /// diff --git a/MongoDbGenericRepository/MongoDbContext.cs b/MongoDbGenericRepository/MongoDbContext.cs index ccb2379..02e1e96 100644 --- a/MongoDbGenericRepository/MongoDbContext.cs +++ b/MongoDbGenericRepository/MongoDbContext.cs @@ -76,23 +76,23 @@ namespace MongoDbGenericRepository .FirstOrDefault() as CollectionNameAttribute)?.Name; } - /// - /// Returns a collection for a document type. Also handles document types with a partition key. - /// - /// The type representing a Document. - /// The optional value of the partition key. - public IMongoCollection GetCollection(string partitionKey = null) + /// + /// Returns a collection for a document type. Also handles document types with a partition key. + /// + /// The type representing a Document. + /// The optional value of the partition key. + public IMongoCollection GetCollection(string partitionKey = null) { return Database.GetCollection(GetCollectionName(partitionKey)); } - /// - /// Drops a collection, use very carefully. - /// - /// The type representing a Document. - public void DropCollection(string partitionKey = null) + /// + /// Drops a collection, use very carefully. + /// + /// The type representing a Document. + public void DropCollection(string partitionKey = null) { - Database.DropCollection(GetCollectionName(partitionKey)); + Database.DropCollection(GetCollectionName(partitionKey)); } ///