使用 Mongo Cursor 时更新文档的正确方法是什么? [英] What is the correct method to update a document while using Mongo Cursor?

查看:60
本文介绍了使用 Mongo Cursor 时更新文档的正确方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用游标更新 Mongo DB 中的文档.我的 Mongo DB Java 驱动程序版本是 3.3.0.以下是我的代码片段.

I am trying to update a document in Mongo DB using cursor. My Mongo DB Java driver version is 3.3.0. Following is my code snippet.

MongoCollection<Document> collection = mongoDb.getCollection("customer");
MongoCursor<Document> cursor = collection.find().iterator();
try{
    while(cursor.hasNext()){
        Document oldDoc = cursor.next();
        //created new Document newDoc
        collection.replaceOne(oldDoc, newDoc);
    }
}catch(Exception e){
    e.printStackTrace();
}

虽然这样,我可以更新文档,我认为这不是有效的方法,因为这里的集合被搜索了 2 次.我想用一些值更新旧文档,然后再更新想要使用诸如 collection.update(oldDoc)collection.save(oldDoc) 之类的方法来保存它而不创建新文档.我搜索并发现了以下帖子.

Though this way, I can update the document, I think this is not the efficient way because here collection is being searched 2 times. I want to update the old document with some values and later on want to save it using some methods like collection.update(oldDoc) or collection.save(oldDoc) without creating a new document. I searched and came across the following post.

Java、MongoDB:如何在迭代一个巨大的集合时更新每个对象?

这正是我想要的,但我在新 API 中找不到 save() 方法.所以我在这里有 3 个问题.

This is exactly what I want, but I don't find save() method in the new API. So I have 3 questions here.

  1. Mongo DB Java 驱动程序 3.3.0 API 中的 save() 方法等效于什么,通过它我可以在迭代游标时更新或保存文档?立>
  2. 无论如何我可以更新现有文档而无需在 Mongo DB Java 驱动程序 3.3.0 API 中创建新文档?
  3. 以上链接显示 save() 早先是 Mongo DB Java 驱动程序 API 的一部分.任何专家的答案,为什么它从 API 中删除?

推荐答案

不用担心额外的搜索,replaceOne 方法的第一个参数是过滤器.使用旧文档作为过滤器将使用文档的 _id 属性,这应该是相对较快的.所以基本上,你这样做的方式是正确的.但请记住,该操作是非事务性的,这意味着更新可能会影响游标的结果集.因此可能会发生,更新的文档将存储在光标尚未经过的位置,导致文档被处理两次.

Don't worry about the additional search, the replaceOne method's first parameter is a filter. Using the old doc as filter will use the _id property of the document which should be relatively fast. So basically, the way you do it, is correct. But bear in mind that the operation is non-transactional, which means the update may affect the cursor's result set. So it could happen, that the updated document will be stored at a positions the cursor has not yet passed, resulting in the document being processed twice.

关于您的问题.

  1. mongo shell 中 save 方法的语义是更新或插入尚不存在的文档(也称为 upsert).MongoCollection 上最接近的是 updateOne() 带有 UpdateOptions upsert 设置为 true.这基本上就是 save 命令所做的.但是 replaceOne 会导致相同的结果,如果替换文档是原始文档的修改版本.

  1. The semantics of save method in mongo shell is to update or insert the document if not yet existing (aka upsert). The closest thing to that on the MongoCollection is updateOne() with an UpdateOptions upsert set to true. That's basically what the save command does. But replaceOne leads to the same result, if the replacement document is a modified version of the original one.

为什么要担心对象创建?在 Java 中,它几乎是免费的,并且不用担心 GC 或内存消耗,因为这些短命对象的 GC 速度非常快.如果你想让代码更简洁,你可以只使用 oldDoc 的 _id 创建一个专用的过滤器对象,修改 oldDoc 并使用它代替新的 Doc.

Why worrying about object creation? In java it comes at next to no cost and don't worry about GC or Memory consumption as those shortlived objects are GC'ed pretty fast. If you want to have code more concise you may create a dedicated filter object with just the _id of the oldDoc, modify the oldDoc and use it instead of the new Doc.

例如:

UpdateOptions upsert = new UpdateOptions().upsert(true);
Bson idFilter = Filters.eq("_id", oldDoc.getObjectId("_id"));
//modify the oldDoc
oldDoc. ...
collection.replaceOne(idFilter, oldDoc, upsert);

这篇关于使用 Mongo Cursor 时更新文档的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆