带有 $in 和 upsert 的 MongoDB UpdateMany

svs*_*eja 5 java mongodb mongodb-java mongodb-query

名为 people1 的 Mongo 集合包含以下数据:

db.persons1.find().pretty();


{ "_id" : "Sims",    "count" : 32 }
{ "_id" : "Autumn",  "count" : 35 }
{ "_id" : "Becker",  "count" : 35 }
{ "_id" : "Cecile",  "count" : 40 }
{ "_id" : "Poole",   "count" : 32 }
{ "_id" : "Nanette", "count" : 31 }
Run Code Online (Sandbox Code Playgroud)

现在通过 Java 我编写了代码来增加列表中用户的计数

MongoClient mongoclient = new MongoClient("localhost", 27017);
MongoDatabase db = mongoclient.getDatabase("testdb1");
MongoCollection<Document> collection = db.getCollection("persons1");
List li = new ArrayList();
li.add("Sims");
li.add("Autumn");

collection.updateMany(
    in("_id",li),
    new Document("$inc", new Document("count", 1)),
    new UpdateOptions().upsert(true));
Run Code Online (Sandbox Code Playgroud)

运行上面的java程序后,我的输出如下。

db.persons1.find().pretty();


{ "_id" : "Sims", "count" : 33 }
{ "_id" : "Autumn", "count" : 36 }
{ "_id" : "Becker", "count" : 35 }
{ "_id" : "Cecile", "count" : 40 }
{ "_id" : "Poole", "count" : 32 }
{ "_id" : "Nanette", "count" : 31 }
Run Code Online (Sandbox Code Playgroud)

我的问题:对于存在于 Array 列表中但不存在于 people1 集合中的条目,是否可以插入并从 1 开始计数?

问题描述:

之前的程序数据库包含的详细信息如下:

{ "_id" : "Sims",    "count" : 33 }
{ "_id" : "Autumn",  "count" : 36 }
{ "_id" : "Becker",  "count" : 35 }
{ "_id" : "Cecile",  "count" : 40 }
{ "_id" : "Poole",   "count" : 32 }
{ "_id" : "Nanette", "count" : 31 }
Run Code Online (Sandbox Code Playgroud)

示例 Java 代码:

MongoClient mongoclient = new MongoClient("localhost", 27017);
MongoDatabase db = mongoclient.getDatabase("testdb1");
MongoCollection<Document> collection = db.getCollection("persons1");
List li = new ArrayList();

// Entry already Present so required to increment by 1
li.add("Sims");

// Entry already Present so required to increment by 1
li.add("Autumn");

// Entry is NOT Present, hence insert into persons data base with "_id" as User1 and count as 1
li.add("User1");

// Entry is NOT Present, hence insert into persons data base with "_id" as User1 and count as 1
li.add("User2");

// Code to be written
Run Code Online (Sandbox Code Playgroud)

从数据库中获取输出的代码应该是什么,如下所示:

{ "_id" : "Sims",    "count" : 34 } // Entry already Present, incremented by 1
{ "_id" : "Autumn",  "count" : 37 } // Entry already Present, incremented by 1
{ "_id" : "Becker",  "count" : 35 }
{ "_id" : "Cecile",  "count" : 40 }
{ "_id" : "Poole",   "count" : 32 }
{ "_id" : "Nanette", "count" : 31 }
{ "_id" : "User1",   "count" : 1 }  // Entry Not Present, start by 1
{ "_id" : "User2",   "count" : 1 }  // Entry Not Present, start by 1
Run Code Online (Sandbox Code Playgroud)

Bla*_*ven 1

这里的“问题”是,$in参数_id不会被解释为_id“多”标记更新中字段的有效“填充符”,这就是您正在做的事情。所有_id值都将由默认值填充,ObjectId而不是“upsert”。

解决这个问题的方法是使用“批量”操作,并且通过 Java 3.x 驱动程序,您可以使用BulkWrite该类和如下结构:

    MongoCollection<Document> collection = db.getCollection("persons1");

    List li = new ArrayList();

    li.add("Sims");
    li.add("User2");

    List<WriteModel<Document>> updates = new ArrayList<WriteModel<Document>>();

    ListIterator listIterator = li.listIterator();

    while ( listIterator.hasNext() ) {
        updates.add(
            new UpdateOneModel<Document>(
                new Document("_id",listIterator.next()),
                new Document("$inc",new Document("count",1)),
                new UpdateOptions().upsert(true)
            )
        );
    }

    BulkWriteResult bulkWriteResult = collection.bulkWrite(updates);
Run Code Online (Sandbox Code Playgroud)

这会将您的基本操作转换ListUpdateOneModel具有适合的列表的对象bulkWrite,并且所有“单独”更新都在一个请求和一个响应中发送,即使它们“技术上”是多个更新语句。

这是通过更新操作设置多个_id键或匹配的唯一有效方法。$in