Spring Data MongoDB基于集合的多租户 [英] Collection based multitenancy with Spring Data MongoDB
问题描述
我们的Spring Boot 1.3.3应用程序使用Spring Data MongoDB 1.8.4将数据持久存储在MongoDB(2.6或3.2)上.
Our Spring Boot 1.3.3 application persists data on MongoDB (2.6 ou 3.2) using Spring Data MongoDB 1.8.4.
我们需要支持多租户.我们选择使用基于集合"的多租户,即每个租户都有自己的集合.例如,对于Article实体,集合是"{tenantName} _articles".
We need to support multitenancy. We chose to use "collection based" multitenancy, i.e. each tenant has its own set of collection. For example for the Article entity, the collections are "{tenantName}_articles".
Oliver Gierke在对spring-data-mongodb进行多次租户使用例如:
Oliver Gierke kindly explained an implementation in Making spring-data-mongodb multi-tenant using for example :
@Document(collectionName = "#{tenantProvider.getTenantId()}_articles")
这在纸上非常好,但是似乎不适用于现实生活中的应用,因为我发现了两个问题,一个是主要问题:
This is very nice on paper, but does not seem applicable for real life applications as I found two issues, one being major:
问题1 (我可以接受):在应用程序启动时,Spring Boot使数据库为具有自定义索引(例如@Indexed属性)的实体建立索引.但是在启动时,没有当前租户",因此Spring Data会创建不相关的集合,例如"_articles".我们如何防止这种情况?
Issue 1 (I could live with that): at application startup Spring Boot makes the database build the indexes for entities that have custom indexes (such as @Indexed attributes). But at startup, there is no "current tenant" so Spring Data creates irrelevant collections such as "_articles". How can we prevent this?
问题2 (此处的主要问题):在运行时,创建并使用了多租户集合(例如"{tenantName} _articles"),并且没有自定义索引(除了"_id"上的默认MongoDB索引).我怀疑Spring在运行时会忽略索引,因为它认为它已经在启动时完成了工作.这是一个主要的性能问题.我们该如何解决?
Issue 2 (major probleme here): at runtime the multitenant collections such as "{tenantName}_articles" are created and used without the custom indexes (apart from the default MongoDB index on "_id"). I suspect Spring ignores indexes at runtime because it thinks it already did the job at startup. This is a major performance problem. How can we fix this?
谢谢您的时间.
推荐答案
找到了一种为给定租户重新创建索引的方法:
Found a way to recreate the indexes for a given tenant:
String tenantName = ...;
MongoMappingContext mappingContext = (MongoMappingContext) mongoTemplate.getConverter().getMappingContext();
MongoPersistentEntityIndexResolver resolver = new MongoPersistentEntityIndexResolver(mappingContext);
for (BasicMongoPersistentEntity entity : mappingContext.getPersistentEntities()) {
if (entity.findAnnotation(Document.class) == null) {
// Keep only collection roots
continue;
}
String collectionName = entity.getCollection();
if (!collectionName.startsWith(tenantName)) {
// Keep only dynamic entities
continue;
}
IndexOperations indexOperations = mongoTemplate.indexOps(collectionName);
for (MongoPersistentEntityIndexResolver.IndexDefinitionHolder holder : resolver.resolveIndexForEntity(entity)) {
indexOperations.ensureIndex(holder.getIndexDefinition());
}
}
花一些时间来解决这个问题.希望这会有所帮助.欢迎改进.
Took me some time to figure this out. Hope this will help. Improvements welcome.
这篇关于Spring Data MongoDB基于集合的多租户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!