Spring Data MongoDB:当文档嵌入另一个文档时如何忽略唯一索引字段?

问题描述 投票:0回答:3

我有一个像这样定义的 Contract 类:

@Document
public class Contract {

    @Id
    private String id;

    @Indexed(unique = true)
    private String ref;

    private String status = "pending";

    // getter & setter & hashcode & equals & tostring...
}

我想随着时间的推移保存合约状态,所以我创建了一个像这样的 Version 类:

@Document
public class Version {

    @Id
    private String id;

    private Contract contract;

    private Instant createdAt;

    // getter & setter & hashcode & equals & tostring...
}

当我尝试随着时间的推移多次保存版本对象时,出现重复键异常。我认为这是合同参考上重复的关键索引,在这里抱怨。

我怎样才能实现这样的目标?

java spring spring-data-mongodb
3个回答
10
投票

只需添加@Reference,如下所示:

@Document
public class Version {

  @Id
  private String id;

  @Reference
  private Contract contract;

  private Instant createdAt;

  // getter & setter & hashcode & equals & tostring...
}

0
投票

我不确定是否有办法从 spring 上下文中实现这一点。

最好的方法是删除代码之外的所有索引定义。即通过离线脚本应用。您可以使用 mongeez 等工具应用脚本。它可以配置为在应用程序启动时运行,因此您可以确保它始终运行,无论位置如何。

应用程序上线后,我们可能希望以受控方式构建新索引。嵌入代码可能不会带来这种优势,因为它只会在启动时运行。

如果您使用离线脚本,您就可以完全控制。


0
投票

我认为你可以使用 eventListener 来创建索引,所以我使用这段代码并成功地没有在嵌入文档上创建索引,你可以尝试这个

@EventListener(ContextRefreshedEvent.class)
public void initIndicesAfterStartup() {

    MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext = mongoTemplate
            .getConverter().getMappingContext();

    IndexResolver resolver = new MongoPersistentEntityIndexResolver(mappingContext);
    // consider only entities that are annotated with @Document
    mappingContext.getPersistentEntities()
            .stream()
            .filter(it -> it.isAnnotationPresent(Document.class))
            .forEach(it -> {
                var indexOps = mongoTemplate.indexOps(it.getType());
                resolver.resolveIndexFor(it.getType()).forEach(indexDefinition -> {
                    var indexHolder = (MongoPersistentEntityIndexResolver.IndexDefinitionHolder) indexDefinition;
                    if (StringUtils.isBlank(indexHolder.getPath())) {
                        indexOps.ensureIndex(indexDefinition);
                    }

                });
            });
}

这段代码的结论

var indexHolder = (MongoPersistentEntityIndexResolver.IndexDefinitionHolder) indexDefinition;

var indexHolder = (MongoPersistentEntityIndexResolver.IndexDefinitionHolder)indexDefinition;

当我们尝试嵌入文档时,不知何故在该字段上使用了indexHolder.getPath()

© www.soinside.com 2019 - 2024. All rights reserved.