使用Mongo Cursor时更新文档的正确方法是什么?

时间:2017-01-20 16:39:45

标签: java mongodb mongodb-java mongodb-java-3.3.0

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

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)而不创建新文档。我搜索并发现了以下帖子。

Java, MongoDB: How to update every object while iterating a huge collection?

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

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

1 个答案:

答案 0 :(得分:0)

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

关于你的问题。

  1. mongo shell中replaceOne方法的语义是更新或插入文档(如果尚未存在(也称为upsert))。与save最接近的是[{3}},其中updateOne() MongoCollection设置为true。这基本上是upsert命令的作用。但如果替换文档是原始文档的修改版本,则save会导致相同的结果。

  2. 为什么担心对象创建?在java中它接下来是免费的,不用担心GC或内存消耗,因为那些短暂的对象是GC非常快。如果您希望代码更简洁,可以使用oldDoc的replaceOne创建专用过滤器对象,修改oldDoc并使用它而不是新文档。

  3. 例如:

    _id