Browse Source

Merge pull request #19073 from abpframework/liangshiwei/mongodb

Allows configuration of MongoDB entity indexes
pull/19087/head
maliming 3 years ago
committed by GitHub
parent
commit
9344c693c0
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 28
      docs/en/MongoDB.md
  2. 28
      docs/zh-Hans/MongoDB.md
  3. 9
      framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IHasCreateCollectionOptions.cs
  4. 10
      framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IHasMongoIndexManagerAction.cs
  5. 10
      framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoEntityModelBuilder.cs
  6. 15
      framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoEntityModelBuilder.cs
  7. 25
      framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoModelBuilder.cs
  8. 13
      framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs
  9. 8
      framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs

28
docs/en/MongoDB.md

@ -82,6 +82,34 @@ If you only need to configure the collection name, you can also use `[MongoColle
public IMongoCollection<Question> Questions => Collection<Question>();
````
### Configure Indexes and CreateCollectionOptions for a Collection
You can configure indexes and `CreateCollectionOptions` for your collections by overriding the `CreateModel` method. Example:
````csharp
protected override void CreateModel(IMongoModelBuilder modelBuilder)
{
base.CreateModel(modelBuilder);
modelBuilder.Entity<Question>(b =>
{
b.CreateCollectionOptions.Collation = new Collation(locale:"en_US", strength: CollationStrength.Secondary);
b.ConfigureIndexes(indexes =>
{
indexes.CreateOne(
new CreateIndexModel<BsonDocument>(
Builders<BsonDocument>.IndexKeys.Ascending("MyProperty"),
new CreateIndexOptions { Unique = true }
)
);
}
);
});
}
````
This example sets a collation for the collection and creates a unique index for the `MyProperty` property.
### Configure the Connection String Selection
If you have multiple databases in your application, you can configure the connection string name for your DbContext using the `[ConnectionStringName]` attribute. Example:

28
docs/zh-Hans/MongoDB.md

@ -51,6 +51,34 @@ public class MyDbContext : AbpMongoDbContext
* 为每一个mongo集合添加一个公共的 `IMongoCollection<TEntity>` 属性.ABP默认使用这些属性创建默认的仓储
* 重写 `CreateModel` 方法,可以在方法中配置集合(如设置集合在数据库中的名字)
### 为集合配置索引和 CreateCollectionOptions
你可以在 `CreateModel` 方法中配置集合的索引和 `CreateCollectionOptions`:
````csharp
protected override void CreateModel(IMongoModelBuilder modelBuilder)
{
base.CreateModel(modelBuilder);
modelBuilder.Entity<Question>(b =>
{
b.CreateCollectionOptions.Collation = new Collation(locale:"en_US", strength: CollationStrength.Secondary);
b.ConfigureIndexes(indexes =>
{
indexes.CreateOne(
new CreateIndexModel<BsonDocument>(
Builders<BsonDocument>.IndexKeys.Ascending("MyProperty"),
new CreateIndexOptions { Unique = true }
)
);
}
);
});
}
````
在这个例子中,我们设置了集合的排序规则和一个唯一的索引.
### 将 Db Context 注入到依赖注入中
在你的模块中使用 `AddAbpDbContext` 方法将Db Context注入到[依赖注入](Dependency-Injection.md)系统中.

9
framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IHasCreateCollectionOptions.cs

@ -0,0 +1,9 @@
using MongoDB.Bson;
using MongoDB.Driver;
namespace Volo.Abp.MongoDB;
public interface IHasCreateCollectionOptions
{
CreateCollectionOptions<BsonDocument> CreateCollectionOptions { get; }
}

10
framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IHasMongoIndexManagerAction.cs

@ -0,0 +1,10 @@
using System;
using MongoDB.Bson;
using MongoDB.Driver;
namespace Volo.Abp.MongoDB;
public interface IHasMongoIndexManagerAction
{
Action<IMongoIndexManager<BsonDocument>>? IndexesAction { get; set; }
}

10
framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoEntityModelBuilder.cs

@ -1,5 +1,7 @@
using System;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Driver;
namespace Volo.Abp.MongoDB;
@ -10,6 +12,10 @@ public interface IMongoEntityModelBuilder<TEntity>
string CollectionName { get; set; }
BsonClassMap<TEntity> BsonMap { get; }
CreateCollectionOptions<BsonDocument> CreateCollectionOptions { get; }
void ConfigureIndexes(Action<IMongoIndexManager<BsonDocument>> action);
}
public interface IMongoEntityModelBuilder
@ -19,4 +25,8 @@ public interface IMongoEntityModelBuilder
string CollectionName { get; set; }
BsonClassMap BsonMap { get; }
CreateCollectionOptions<BsonDocument> CreateCollectionOptions { get; }
void ConfigureIndexes(Action<IMongoIndexManager<BsonDocument>> action);
}

15
framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoEntityModelBuilder.cs

@ -1,19 +1,28 @@
using MongoDB.Bson.Serialization;
using System;
using MongoDB.Bson;
using MongoDB.Driver;
namespace Volo.Abp.MongoDB;
public class MongoEntityModelBuilder<TEntity> :
IMongoEntityModel,
IHasBsonClassMap,
IHasCreateCollectionOptions,
IHasMongoIndexManagerAction,
IMongoEntityModelBuilder,
IMongoEntityModelBuilder<TEntity>
{
public Type EntityType { get; }
public string CollectionName { get; set; } = default!;
public Action<IMongoIndexManager<BsonDocument>>? IndexesAction { get; set; }
public CreateCollectionOptions<BsonDocument> CreateCollectionOptions { get; }
BsonClassMap IMongoEntityModelBuilder.BsonMap => _bsonClassMap;
BsonClassMap<TEntity> IMongoEntityModelBuilder<TEntity>.BsonMap => _bsonClassMap;
private readonly BsonClassMap<TEntity> _bsonClassMap;
@ -23,10 +32,16 @@ public class MongoEntityModelBuilder<TEntity> :
EntityType = typeof(TEntity);
_bsonClassMap = new BsonClassMap<TEntity>();
_bsonClassMap.ConfigureAbpConventions();
CreateCollectionOptions = new CreateCollectionOptions<BsonDocument>();
}
public BsonClassMap GetMap()
{
return _bsonClassMap;
}
public void ConfigureIndexes(Action<IMongoIndexManager<BsonDocument>>? indexesAction)
{
IndexesAction = indexesAction;
}
}

25
framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoModelBuilder.cs

@ -74,7 +74,10 @@ public class MongoModelBuilder : IMongoModelBuilder
baseClasses.AddRange(entityModel.EntityType.GetBaseClasses(includeObject: false));
CreateCollectionIfNotExists(dbContext, entityModel.CollectionName);
var createCollectionOptions = entityModel.As<IHasCreateCollectionOptions>().CreateCollectionOptions;
var indexesAction = entityModel.As<IHasMongoIndexManagerAction>().IndexesAction;
CreateCollectionIfNotExists(dbContext, entityModel.CollectionName, createCollectionOptions);
CreateCollectionIndexes(dbContext, entityModel.CollectionName, indexesAction);
}
baseClasses = baseClasses.Distinct().ToList();
@ -141,7 +144,7 @@ public class MongoModelBuilder : IMongoModelBuilder
typeof(MongoEntityModelBuilder<>).MakeGenericType(entityType)
)!
);
buildAction?.Invoke(model);
}
@ -150,14 +153,24 @@ public class MongoModelBuilder : IMongoModelBuilder
return _entityModelBuilders.Values.Cast<IMongoEntityModel>().ToImmutableList();
}
protected virtual void CreateCollectionIfNotExists(AbpMongoDbContext dbContext, string collectionName)
protected virtual void CreateCollectionIfNotExists(AbpMongoDbContext dbContext, string collectionName, CreateCollectionOptions createCollectionOptions)
{
var filter = new BsonDocument("name", collectionName);
var options = new ListCollectionNamesOptions { Filter = filter };
var options = new ListCollectionsOptions { Filter = filter };
if (!dbContext.Database.ListCollections(options).Any())
{
dbContext.Database.CreateCollection(collectionName, createCollectionOptions);
}
}
if (!dbContext.Database.ListCollectionNames(options).Any())
protected virtual void CreateCollectionIndexes(AbpMongoDbContext dbContext, string collectionName, Action<IMongoIndexManager<BsonDocument>>? indexesAction = null)
{
var collection = dbContext.Database.GetCollection<BsonDocument>(collectionName);
if (collection != null)
{
dbContext.Database.CreateCollection(collectionName);
indexesAction?.Invoke(collection.Indexes);
}
}
}

13
framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs

@ -3,6 +3,7 @@ using System.Linq;
using System.Threading.Tasks;
using MongoDB.Driver.Linq;
using Shouldly;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.TestApp;
using Volo.Abp.TestApp.Domain;
using Volo.Abp.TestApp.Testing;
@ -64,4 +65,16 @@ public class Repository_Basic_Tests : Repository_Basic_Tests<AbpMongoDbTestModul
person.Phones.Count.ShouldBe(1);
person.Phones.Any(p => p.PersonId == person.Id && p.Number == "1234567890").ShouldBeTrue();
}
[Fact]
public async Task Filter_Case_Insensitive()
{
(await CityRepository.GetMongoQueryableAsync()).FirstOrDefault(c => c.Name == "ISTANBUL").ShouldBeNull();
(await CityRepository.GetMongoQueryableAsync()).FirstOrDefault(c => c.Name == "istanbul").ShouldBeNull();
(await CityRepository.GetMongoQueryableAsync()).FirstOrDefault(c => c.Name == "Istanbul").ShouldNotBeNull();
(await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "douglas").ShouldNotBeNull();
(await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "DOUGLAS").ShouldNotBeNull();
(await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "Douglas").ShouldNotBeNull();
}
}

8
framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs

@ -1,4 +1,5 @@
using MongoDB.Driver;
using MongoDB.Bson;
using MongoDB.Driver;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EntityFrameworkCore.TestApp.FourthContext;
@ -35,5 +36,10 @@ public class TestAppMongoDbContext : AbpMongoDbContext, ITestAppMongoDbContext,
{
b.CollectionName = "MyCities";
});
modelBuilder.Entity<Person>(b =>
{
b.CreateCollectionOptions.Collation = new Collation(locale:"en_US", strength: CollationStrength.Secondary);
});
}
}

Loading…
Cancel
Save