Collection based multitenancy with Spring Data MongoDB

最后都变了- 提交于 2019-12-01 18:08:44

问题


Our Spring Boot 1.3.3 application persists data on MongoDB (2.6 ou 3.2) using Spring Data MongoDB 1.8.4.

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 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:

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?

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?

Thank you for your time.


回答1:


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.



来源:https://stackoverflow.com/questions/37459810/collection-based-multitenancy-with-spring-data-mongodb

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!