更新查询中的 MongoTemplate 确定性顺序

Posted

技术标签:

【中文标题】更新查询中的 MongoTemplate 确定性顺序【英文标题】:MongoTemplate deterministic order in update query 【发布时间】:2022-01-08 18:46:59 【问题描述】:

我在我的 Spring Batch 编写器中使用 MongoTemplate,并且我想使用 $addToSet 运算符将我的元素推送到数组中,前提是它们尚不存在。 我在 Mongodb 文档中看到,$addToSet只有在字段顺序相同时才起作用

所以我的问题是:MongoTemplate 是否总是以相同的顺序将我的 pojo 转换为 Bson 文档?

我在 MongoTemplate 的代码 (MappingMongoConverter) 中找到了这个转换器,对我来说,循环不是确定性的:

private void writeProperties(Bson bson, MongoPersistentEntity<?> entity, PersistentPropertyAccessor<?> accessor,
        DocumentAccessor dbObjectAccessor, @Nullable MongoPersistentProperty idProperty) 

    // Write the properties
    for (MongoPersistentProperty prop : entity) 

        if (prop.equals(idProperty) || !prop.isWritable()) 
            continue;
        
        if (prop.isAssociation()) 
            writeAssociation(prop.getRequiredAssociation(), accessor, dbObjectAccessor);
            continue;
        

        Object value = accessor.getProperty(prop);

        if (value == null) 
            continue;
        

        if (!conversions.isSimpleType(value.getClass())) 
            writePropertyInternal(value, dbObjectAccessor, prop);
         else 
            writeSimpleInternal(value, bson, prop);
        
    

【问题讨论】:

“我在 Mongodb 文档中看到 $addToSet 仅在字段顺序相同时才有效。” - 我看到 没有这样的规则 在 MongoDB 手册中提到。 $addToSet update 运算符将元素添加到数组字段如果元素不存在。 From docs.mongodb.com/manual/reference/operator/update/addToSet : "如果值是一个文档,如果数组中的现有文档与待添加的文档完全匹配,则MongoDB确定该文档是重复的;即现有文档具有完全相同的字段和值,并且字段的顺序相同。因此,字段顺序很重要,您不能指定 MongoDB 仅比较文档中的一部分字段来确定文档是否是现有数组元素的副本。" 那是针对数组字段元素为子文档(或对象)的场景。 是的,这是我的情况,数组包含文档,这就是我询问 MongoTemplate“编组”顺序的原因。抱歉,如果不清楚。 【参考方案1】:

Spring Mongo @Field 注解允许显式设置每个字段的顺序。

我的一些 POJO 有 1000 个字段,在我的情况下这是一个费力的解决方案,但却是一个解决方案。 如果有人知道更简单的方法,我将不胜感激:)

来源:https://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/mapping/Field.html

【讨论】:

以上是关于更新查询中的 MongoTemplate 确定性顺序的主要内容,如果未能解决你的问题,请参考以下文章

mongoTemplate query update (指定查询哪些字段)

MongoTemplate实现根据某个字段分类查询

MongoTemplate 一次更新多个文档而不使用 saveAll() 或循环

mongoTemplate 过滤查询出来的字段(可以把_idclass字段去掉)

mongoTemplate 组合条件查询 的问题

MongoTemplate 至少匹配我传递的值的查询数组