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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With