首页 文章

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

提问于
浏览
4

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

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

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

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

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

Issue 1 (我可以忍受):在应用程序启动时,Spring Boot使数据库为具有自定义索引的实体(例如@Indexed属性)构建索引 . 但在启动时,没有"current tenant"所以Spring Data会创建无关的集合,例如"_articles" . 我们怎么能阻止这个?

Issue 2 (此处主要问题):在运行时,创建多租户集合,如"_articles",并使用 without the custom indexes (除了"_id"上的默认MongoDB索引) . 我怀疑Spring会在运行时忽略索引,因为它认为它已经在启动时完成了工作 . 这是一个主要的性能问题 . 我们该如何解决这个问题?

感谢您的时间 .

1 回答

  • 5

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

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

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

相关问题