首页 > 解决方案 > In Spring MongoDB update, MonogDB doc replaced/lost fields, becomes empty, oplog "o" for this update has no $set, $unset, has only objectId as in "o2"

问题描述

Context:

Issue :

After an update operation performed, document in collection lost all the data and kept only ObjectId in it.

Checking the oplog entry found an unusual value, understand that the o2field ObjectId says the object to be updated and ofield says about operations being performed/updated.

In this particular instance o2field has the expected value, but o field also has the same value instead of the update operation details to be done.

Question :

Any idea when can we expect such an oplog as mentioned below without $set or $unset for update operations ?

After this operation, actual document with ObjectId in collection lost all the fields except ObjectId.

{
        "ts" : Timestamp(1596778564, 9),
        "t" : NumberLong(7),
        "h" : NumberLong(0),
        "v" : 2,
        "op" : "u",
        "ns" : "db.collectionName",
        "ui" : UUID("2947862a-8fb7-4342-87d1-a0ab5f8bc0bd"),
        "o2" : {
                "_id" : ObjectId("5f27e94e0174081a3feb5c6b")
        },
        "wall" : ISODate("2020-08-07T05:36:04.402Z"),
        "lsid" : {
                "id" : UUID("cbd4b90f-1bff-4ad1-b4e2-4c286fc25450"),
                "uid" : BinData(0,"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=")
        },
        "txnNumber" : NumberLong(1269),
        "stmtId" : 0,
        "prevOpTime" : {
                "ts" : Timestamp(0, 0),
                "t" : NumberLong(-1)
        },
        "o" : {
                "_id" : ObjectId("5f27e94e0174081a3feb5c6b")
        }
}

The update oplog for the same object few milliseconds ago is given below. Which has the right set of operations.

{
        "ts" : Timestamp(1596778564, 8),
        "t" : NumberLong(7),
        "h" : NumberLong(0),
        "v" : 2,
        "op" : "u",
        "ns" : "db.collectionName",
        "ui" : UUID("2947862a-8fb7-4342-87d1-a0ab5f8bc0bd"),
        "o2" : {
                "_id" : ObjectId("5f27e94e0174081a3feb5c6b")
        },
        "wall" : ISODate("2020-08-07T05:36:04.398Z"),
        "lsid" : {
                "id" : UUID("cbd4b90f-1bff-4ad1-b4e2-4c286fc25450"),
                "uid" : BinData(0,"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=")
        },
        "txnNumber" : NumberLong(1268),
        "stmtId" : 0,
        "prevOpTime" : {
                "ts" : Timestamp(0, 0),
                "t" : NumberLong(-1)
        },
        "o" : {
                "$v" : 1,
                "$set" : {
                        .....
                       .......
                      ......... //All the values to be updated
                }
        }
}

标签: mongodbspring-data-mongodbmongodb-oplog

解决方案


希望它也像我一样对 Spring-MongoDB 中的一些人有所帮助。

尝试了以下代码,在调用时未设置任何值时会发生这种update情况mongoTemplate.updateFirst。如果该行update.set未注释,则可以正常工作。当更新中没有设置任何内容时,它将它作为替换文档。

@Override
    public void run(String... args) throws Exception {
        customerRepository.deleteAll();

        customerRepository.save(new Customer("Bob","S"));
        customerRepository.save(new Customer("Alice","Smith"));

        findAll();

        Update update = new Update();
//      update.set("firstName", "Bobby");

        Query query = Query.query(Criteria.where("lastName").is("S"));
        mongoTemplate.updateFirst(query, update, "customer");

        findAll();
    }

进一步检查我们的代码,发现set基于updateCONDITION IF 要设置的值是否可用,它似乎工作正常,只要这些值可用并且set被调用update。如果值不可设置,set则不调用Update设置值,将其作为替换并替换集合中的整个文档。


推荐阅读