MongoDB 使用 $in 和 upsert 的 UpdateMany

MongoDB UpdateMany with $in and upsert

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

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 }

现在到 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));

在我 运行 上述 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 }

我的问题:对于 Array 列表中存在但 persons1 集合中不存在的条目,是否可以插入并从 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 }

示例 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

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

{ "_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

此处的 "catch" 是 _id$in 参数将不会被解释为 _id 字段的有效 "filler" "multi" 标记更新,这是你正在做的。默认情况下,将填充所有 _idObjectId 值,而不是 "upsert".

解决这个问题的方法是使用 "Bulk" 操作,并且对于 Java 3.x 驱动程序,您可以使用 BulkWrite class 和类似的构造这个:

    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);

这会将您的基本 List 操纵为 UpdateOneModel objects with a list that is suitable for bulkWrite,并且所有 "individual" 更新都在一个请求和一个响应中发送,即使它们是 "technically" 多个更新报表。

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