使用Spring Data MongoDB进行基于集合的多租户

时间:2016-05-26 11:38:23

标签: mongodb spring-data multi-tenant spring-data-mongodb

我们的Spring Boot 1.3.3应用程序使用Spring Data MongoDB 1.8.4在MongoDB(2.6 ou 3.2)上保留数据。

我们需要支持多租户。我们选择使用“基于集合”的多租户,即每个租户都有自己的集合。例如,对于Article实体,集合是“{tenantName} _articles”。

Oliver Gierke在Making spring-data-mongodb multi-tenant中解释了一个实现,例如:

@Document(collectionName = "#{tenantProvider.getTenantId()}_articles")

这在纸上非常好,但似乎不适用于现实生活中的应用程序,因为我发现了两个问题,一个是主要问题:

问题1 (我可以忍受):在应用程序启动时,Spring Boot使数据库为具有自定义索引的实体(例如@Indexed属性)构建索引。但在创业时,没有“当前租户”,因此Spring Data创建了无关的集合,例如“_articles”。我们怎样才能阻止这种情况?

第2期(此处主要问题):在运行时创建多租户集合,例如“{tenantName} _articles”,并使用而不使用自定义索引(除了“_id”上的默认MongoDB索引。我怀疑Spring在运行时会忽略索引,因为它认为它已经在启动时完成了工作。这是一个主要的性能问题。我们如何解决这个问题?

感谢您的时间。

1 个答案:

答案 0 :(得分:7)

找到一种方法为给定的租户重新创建索引:

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());
    }
}

我花了一些时间来弄明白这一点。希望这会有所帮助。欢迎改进。