Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bulk Upsert with MongoDB Java 3.0 Driver

In the earlier versions of MongoDB Java drivers , to run a query and do unordered bulk upsert on the result all we had do was :

BulkWriteOperation bulk = dbCollection.initializeUnorderedBulkOperation();
    bulk.find(searchQuery).upsert().update(new BasicDBObject("$set", getDbObjectModel()));

But in version 3, with the introduction of Bson Document support and MongoCollection.bulkWrite() method how can this be done?

I tried this :

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

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

but, I need the upsert functionality.

Thanks.

like image 811
void Avatar asked Jul 17 '15 07:07

void


2 Answers

You can still use all of the functionality, it's just that BulkWrites now have a different syntax:

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

So you use the UpdateOneModel ( or for many if you want ) and set the UpdateOptions as the third argument to the constructor.

Takes some getting used to, but it's basically just building "Lists" with all the same syntax as elsewhere. I guess that's the main reason for the change.

like image 60
Blakes Seven Avatar answered Nov 03 '22 20:11

Blakes Seven


Here is the example using latest APIs..

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

Details at: https://ashutosh-srivastav-mongodb.blogspot.in/2017/09/mongodb-bulkwrite-java-api.html

like image 36
Ashutosh Srivastav Avatar answered Nov 03 '22 22:11

Ashutosh Srivastav