Spring Data MongoDB and Bulk Update

I am using Spring Data MongoDB and would like to perform a Bulk Update just like the one described here: http://docs.mongodb.org/manual/reference/method/Bulk.find.update/#Bulk.find.update

When using regular driver it looks like this:

The following example initializes a Bulk() operations builder for the items collection, and adds various multi update operations to the list of operations.

var bulk = db.items.initializeUnorderedBulkOp();
bulk.find( { status: "D" } ).update( { $set: { status: "I", points: "0" } } );
bulk.find( { item: null } ).update( { $set: { item: "TBD" } } );
bulk.execute()

Is there any way to achieve similar result with Spring Data MongoDB ?


Bulk updates are supported from spring-data-mongodb 1.9.0.RELEASE. Here is a sample:

BulkOperations ops = template.bulkOps(BulkMode.UNORDERED, Match.class);
for (User user : users) {
    Update update = new Update();
    ...
    ops.updateOne(query(where("id").is(user.getId())), update);
}
ops.execute();

You can use this as long as the driver is current and the server you are talking to is at least MongoDB, which is required for bulk operations. Don't believe there is anything directly in spring data right now (and much the same for other higher level driver abstractions), but you can of course access the native driver collection object that implements the access to the Bulk API:

    DBCollection collection = mongoOperation.getCollection("collection");
    BulkWriteOperation bulk = collection.initializeOrderedBulkOperation();

    bulk.find(new BasicDBObject("status","D"))
        .update(new BasicDBObject(
            new BasicDBObject(
                "$set",new BasicDBObject(
                    "status", "I"
                ).append(
                    "points", 0
                )
            )
        ));

    bulk.find(new BasicDBObject("item",null))
        .update(new BasicDBObject(
            new BasicDBObject(
                "$set", new BasicDBObject("item","TBD")
            )
        ));


    BulkWriteResult writeResult = bulk.execute();
    System.out.println(writeResult);

You can either fill in the DBObject types required by defining them, or use the builders supplied in the spring mongo library which should all support "extracting" the DBObject that they build.


public <T> void bulkUpdate(String collectionName, List<T> documents, Class<T> tClass) {
    BulkOperations bulkOps = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, tClass, collectionName);
    for (T document : documents) {
        Document doc = new Document();
        mongoTemplate.getConverter().write(document, doc);
        org.springframework.data.mongodb.core.query.Query  query = new org.springframework
            .data.mongodb.core.query.Query(Criteria.where(UNDERSCORE_ID).is(doc.get(UNDERSCORE_ID)));
        Document updateDoc = new Document();
        updateDoc.append("$set", doc);
        Update update = Update.fromDocument(updateDoc, UNDERSCORE_ID);
        bulkOps.upsert(query, update);
    }
    bulkOps.execute();
}

Spring Mongo template is used to perform the update. The above code will work if you provide the _id field in the list of documents.