当前位置: 首页 > 知识库问答 >
问题:

是否使用Spring Data mongodb更新嵌入式mongodb文档中的数组字段?

蒋浩
2023-03-14

我正在尝试使用Spring Data mongodb更新mongodb中嵌入文档中的数组字段。

我想在mongodb集合中更新/插入的文档结构如下所示。

可以有更多这样的文档基于每个类型的部门,如“销售”,“市场营销”等。

{
    "timestamp": "2014-09-26T04:00:00.000Z",
    "department": "accounts",
    "employee": [
        {
            "type": "regular",
            "names": [
                "Raj",
                "Kumar",
                "Shankar"
            ]
        },
        {
            "type": "contract",
            "names": [
                "Penny",
                "Sheldon",
                "bob"
            ]
        },
        {
            "type": "temp",
            "names": [
                "jerry",
                "kramer",
                "bubbleboy"
            ]
        }
    ]
}
db.getCollection('mytest').update(
   { 
        "timestamp" : "2014-09-26T04:00:00.000Z",
        "department" : "accounts",
        "employee.type" : "regular"
    },
    { $addToSet: { "employee.$.names" : "Jo" } },
    {
        upsert: true
    }
)
   The positional operator did not find the match needed from the query. Unexpanded update: employee.$.names

即使这样做有效,我也不确定在Spring Data MongoDB中实现相同的功能是否有类似的支持。

另外,我的另一个查询是,如果我想为多个部门添加/更新员工,比如“Accounts”和“Sales”,似乎我必须执行相同的查询,其值与我想相应更新的部门编号不同(如果不存在插入)。

是否有一个更好和更有效的选项,如批量/批处理,其中-在一个mongo更新查询中,我可以同时更新/插入多个部门的员工。另外,在spring data MongoDB/MongoTemplate中是否有对此的支持。

共有1个答案

祁正浩
2023-03-14

首先,我应该说,有多个场景需要处理,因为文档结构有嵌入数组。如果可能,请尝试重新设计文档结构。

错误的简短回答:-如果查询没有找到匹配的文档,您将得到位置操作符错误。

这就是为什么在下面的解决方案中,我在catch块中处理了这个场景。如果你能通过单元测试,你应该能理解。

public Boolean updateDepartmentCollectionWithoutFind(String name, String timeStamp)
            throws JsonParseException, JsonMappingException, IOException {

        MongoOperations mongoOperations = getMongoConnection();

        Query query = new Query();
        query.addCriteria(Criteria.where("timestamp").is(timeStamp).and("department").is("accounts")
                .and("employee.type").is("regular"));
        Update update = new Update();
        update.addToSet("employee.$.names", name);

        try {

            System.out.println(query.toString());
            System.out.println(update.toString());

            WriteResult writeResult = mongoOperations.upsert(query, update, DepartmentCollection.class);

            if (writeResult != null) {

                System.out.println("111111111111111111 Update with position parameter has been successful :"
                        + writeResult.toString());

            }
        } catch (DataIntegrityViolationException die) {
            System.out.println("Update failed ====>" + die.getMessage());
            System.out.println("Trying to update without position parameters ...");

            Update updateWithoutPositionOperator = new Update();
            updateWithoutPositionOperator.addToSet("employee.names", name);
            WriteResult writeResultUpsert = mongoOperations.upsert(query, updateWithoutPositionOperator,
                    DepartmentCollection.class);

            if (writeResultUpsert != null) {

                System.out.println("2222222222222222222 Update without position parameter has been successful :"
                        + writeResultUpsert.toString());

            }

        }

        return true;

    }
@SuppressWarnings("resource")
public MongoOperations getMongoConnection() {

    return (MongoOperations) new AnnotationConfigApplicationContext(SpringMongoConfig.class)
            .getBean("mongoTemplate");
}
@Test
    public void updateDepartmentCollectionWhenNoDocumentsPresent() throws JsonParseException, JsonMappingException, IOException {

        //Second upsert executed (i.e. without positional parameter)
        Assert.isTrue(queryOperations.updateDepartmentCollectionWithoutFind("Raj", "2014-09-26T04:00:00.000Z"));

    }

    @Test
    public void updateDCWhenMatchingDocumentsPresentButDocumentHasOnlyRegularEmployeeType() throws JsonParseException, JsonMappingException, IOException {

        //Second upsert executed  (i.e. without positional parameter)       
        Assert.isTrue(queryOperations.updateDepartmentCollectionWithoutFind("Jo", "2014-09-26T04:00:00.000Z"));

    }   

    @Test
    public void updateDCWhenMultipleTypesPresentButNoRegular() throws JsonParseException, JsonMappingException, IOException {

        //First upsert executed  (i.e. with positional parameter). However, it creates a new document.      
        Assert.isTrue(queryOperations.updateDepartmentCollectionWithoutFind("Jo", "2014-09-27T04:00:00.000Z"));

    }   

    @Test
    public void updateDCWhenMultipleTypesPresentIncludingRegular() throws JsonParseException, JsonMappingException, IOException {

        //First upsert executed (i.e. with positional parameter) and existing document has been updated.        
        Assert.isTrue(queryOperations.updateDepartmentCollectionWithoutFind("Jo", "2014-09-29T04:00:00.000Z"));

    }
 类似资料:
  • null 这些操作似乎效率不高。但是这种类型的更新是无处不在的,我相信开发者已经考虑到了这一点。那么,我哪里搞错了?

  • 我需要更新Mongo DB中另一个文档内的数组中的一个文档

  • 婴儿步 我尝试使用聚合管道,并在最后一步中通过匹配和查找它们的内容来替换。我不太熟悉通过聚合管道解决这个问题。

  • 我想在具有指定 URL 的相应文档中将嵌套的“已爬行”更新为 True。 我对mongodb相当陌生,我似乎无法弄清楚这一点,非常感谢任何帮助。

  • 问题内容: 我正在使用MongoDB数据库,该数据库的收集模型包括 班级 , 学生 , 学科 和[学术] 表现 。以下是基于猫鼬的架构和模型: 该集合的文件是最复杂的地段; 示例文档为: 我能够使用以下代码检索现有的班级文档并将其添加到分数中: 但是,如何添加/更新/删除该特定学生的成绩?我需要能够通过以下方式与集合进行交互: 检索所有学生或特定学生的分数(检索数组中的特定元素) 为特定主题添加/

  • 问题内容: 我的文档中具有以下结构: 我想更新 someField 和 someField2, 但仅更新数组中的一项,与 _arrayId 匹配的 项 (例如;并且仅针对此文档(例如)),而不更新其他项。 该 arrayIds 是不是唯一的,这就是为什么我需要它是针对特定文档的文档。如果要为数组中存在的每个文档更新该值,则可以使用,但这不是我想要的。 我试图在Java中完成此操作,但也可以使用命令