Java 使用Mongo游标更新文档的正确方法是什么?

Java 使用Mongo游标更新文档的正确方法是什么?,java,mongodb,mongodb-java,mongodb-java-3.3.0,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()){

我正在尝试使用游标更新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();
}
MongoCollection collection=mongoDb.getCollection(“客户”);
MongoCursor=collection.find().iterator();
试一试{
while(cursor.hasNext()){
Document oldDoc=cursor.next();
//创建了新文档newDoc
collection.replaceOne(旧文档、新文档);
}
}捕获(例外e){
e、 printStackTrace();
}
通过这种方式,我可以更新文档,我认为这不是一种有效的方式,因为这里的集合被搜索了2次。我想用一些值更新旧文档,然后用一些方法保存它,如collection.update(oldDoc)或collection.save(oldDoc),而不创建新文档。我搜索了一下,发现了下面的帖子

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

  • Mongo DB Java driver 3.3.0 API中的save()方法等价于什么?通过该方法,我可以在迭代光标时更新或保存文档
  • 在Mongo DB Java driver 3.3.0 API中,我是否可以更新现有文档而不创建新文档
  • 上面的链接显示,save()是早期Mongo DB Java驱动程序API的一部分。任何专家的答案,为什么它被从API中删除

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

    关于你的问题

  • mongoshell中的
    save
    方法的语义是更新或插入文档(如果还不存在的话)(又称upsert)。最接近
    MongoCollection
    的是
    upsert
    设置为true。这就是
    save
    命令的基本功能。但是如果替换文档是原始文档的修改版本,则
    replaceOne
    会导致相同的结果

  • 为什么要担心对象创建?在java中,它几乎是免费的,而且不必担心GC或内存消耗,因为这些短期对象的GC处理速度非常快。如果您想让代码更简洁,可以创建一个专用的筛选对象,只使用oldDoc的
    \u id
    ,修改oldDoc并使用它而不是新文档

  • 例如:

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

    你能看一下吗?
    findOneAndUpdate()
    ?当只有一个文档与筛选器匹配时,两者的行为方式相同。但当多个文档匹配时,行为会有所不同。它还返回未修改的文档,但如果更新的文档依赖于该数据,FindUpdate将不会帮助您。从技术上讲,
    findAndUpdate
    findAndModify
    是一个命令,而
    save()
    是一个
    insert()
    如果更新的文档有
    \u id
    或者
    update()
    如果没有
    \u id
    则是一个带有upsert=true的
    更新()
    。我仍然不明白
    replaceOne
    如何更接近
    save()
    。您不能使用
    replaceOne
    修改(更新)。您可以使用
    update*
    ,它更接近我前面提到的
    save
    find*update*
    。这些方法中有许多具有相似和重叠的行为以及细微的差异,取决于要替换的文档,结果行为可能与update相同。为了理解这种行为,有时查看实现会有所帮助,即在shell
    db中。yourCollection.save
    (不带括号)显示javascript实现
    save
    通过
    insert
    update
    实现,
    findAndModify
    是一个命令,
    replaceOne
    是一个批量操作。但是java驱动程序中没有
    save
    ,最接近的函数是update,upsert=true。