使用MongoDB Java 3.0驱动程序进行批量Upsert

13
在MongoDB Java驱动程序的较早版本中,要在查询并对结果进行无序批量更新,我们所要做的就是:
BulkWriteOperation bulk = dbCollection.initializeUnorderedBulkOperation();
    bulk.find(searchQuery).upsert().update(new BasicDBObject("$set", getDbObjectModel()));

但是在版本3中,随着Bson文档支持和MongoCollection.bulkWrite()方法的引入,如何实现呢?
我尝试了这个:
List<WriteModel<Document>> documentList = new ArrayList<>();

collection.bulkWrite(documentList, new BulkWriteOptions().ordered(false));

但是,我需要upsert功能。

谢谢。

3个回答

26

您仍然可以使用所有功能,只是BulkWrites现在具有不同的语法:

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

    List<WriteModel<Document>> updates = Arrays.<WriteModel<Document>>asList(
        new UpdateOneModel<Document>(
                new Document(),                   // find part
                new Document("$set",1),           // update part
                new UpdateOptions().upsert(true)  // options like upsert
        )
    );

    BulkWriteResult bulkWriteResult = collection.bulkWrite(updates);
所以您可以使用 UpdateOneModel(或者如果需要,可以使用多个),并将UpdateOptions设置为构造函数的第三个参数。需要花一些时间来适应,但基本上只是使用与其他地方完全相同的语法构建“列表”。我猜这就是更改的主要原因。

这些驱动程序的更改有官方文档吗? - void
2
@AswinJoseRoy 有例子吗?没有。不幸的是,所有文档示例(至少官方的)似乎都遵循旧类。对于大多数语言驱动程序也是如此。对我来说,我通过在存储库中搜索“测试”等内容来获取更多信息。但同样,一些“测试”仍然使用旧类。因此,需要进行试错。会变得更好,像您这样的问题实际上有所帮助。 - Blakes Seven
在第一次插入数据时,bulkWriteResult的insertedCount和ModifiedCount都为零,这是一个错误吗? - inza9hi

10

以下是使用最新API的示例代码..

for (Long entityId : entityIDs) {

    //Finder doc
    Document filterDocument = new Document();
    filterDocument.append("_id", entityId);

    //Update doc
    Document updateDocument = new Document();
    Document setDocument = new Document();
    setDocument.append("name", "xyz");
    setDocument.append("role", "abc");

    updateDocument.append("$set", setDocument);

    //Update option
    UpdateOptions updateOptions = new UpdateOptions();
    updateOptions.upsert(true); //if true, will create a new doc in case of unmatched find
    updateOptions.bypassDocumentValidation(true); //set true/false

    //Prepare list of Updates
    updateDocuments.add(
            new UpdateOneModel<Document>(
                    filterDocument,
                    updateDocument,
                    updateOptions));

}

//Bulk write options
BulkWriteOptions bulkWriteOptions = new BulkWriteOptions();
bulkWriteOptions.ordered(false);
bulkWriteOptions.bypassDocumentValidation(true);

MongoCollection<Document> mongoCollection = mongoDB.getCollection("myCollection");

BulkWriteResult bulkWriteResult = null;
try {
    //Perform bulk update
    bulkWriteResult = mongoCollection.bulkWrite(updateDocuments,
            bulkWriteOptions);
} catch (BulkWriteException e) {
    //Handle bulkwrite exception
    List<BulkWriteError> bulkWriteErrors = e.getWriteErrors();
    for (BulkWriteError bulkWriteError : bulkWriteErrors) {
        int failedIndex = bulkWriteError.getIndex();
        Long failedEntityId = entityIDs.get(failedIndex);
        System.out.println("Failed record: " + failedEntityId);
        //handle rollback
    }
}

int rowsUpdated = bulkWriteResult.getModifiedCount();

详情请见:https://ashutosh-srivastav-mongodb.blogspot.in/2017/09/mongodb-bulkwrite-java-api.html


1
这适用于最新版本的Java mongo驱动程序:3.6.0-rc0在中央仓库上。 - Binita Bharati
+1 它可行,“List<WriteModel<Document>> updateDocuments = new ArrayList<WriteModel<Document>>();” 链接已损坏,这是正确的链接:http://ashutosh-srivastav-mongodb.blogspot.com/2017/09/mongodb-bulkwrite-java-api.html - Eswar Goud

0

如果你想使用 findAndModifyElseCreate() 函数,那么意味着如果文档存在,则更新它,否则创建并插入数据,请遵循以下步骤。

BasicDBObject insertInCaseDocumentNotFound = new BasicDBObject();


insertInCaseDocumentNotFound.put("field1", "value1");
insertInCaseDocumentNotFound.put("date", new Date());


MongoCollection<BasicDBObject> table = db.getCollection("collectionName",BasicDBObject.class);

BasicDBObject updateObject = new BasicDBObject();

updateObject.append("$setOnInsert", new BasicDBObject());
updateObject.append("$set", new BasicDBObject("date",new Date());

List<WriteModel<BasicDBObject>> updates = Arrays.<WriteModel<BasicDBObject>> asList(
                new UpdateOneModel<BasicDBObject>(new BasicDBObject("search_name", alert.getString("search_name")), // query for which we need to apply

                        updateObject, // update the document in case it is found
                        new UpdateOptions().upsert(true) // upsert to insert new data in case document is not found
        ));
table.bulkWrite(updates);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接