update multiple documents in mongodb from spring mongo - mongodb

In my use case I want to update multiple documents at once, documents that match a query, using spring-data-mongo.
Here is what I have been trying,
Criteria filterCriteria = new Criteria().andOperator(Criteria.where("bac").is("def"));
Update update = new Update();
update.set("status", status);
Query query = new Query();
query.addCriteria(filterCriteria);
mongoOperations.findAndModify(query, update, MyClass.class);
But this is not updating any document.
Plus I have looked up in the mongo documentation but have not anything useful
https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/#comparisons-with-the-update-method
Here is the version that I am using
Mongodb - 3.6
spring-data-mongodb - 1.5.5.RELEASE

findAndModify(...) method can update a document and return either the old or newly updated document in a single operation.
To update all document that matches the given query use updateMulti(...).
https://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/MongoOperations.html#updateMulti-org.springframework.data.mongodb.core.query.Query-org.springframework.data.mongodb.core.query.UpdateDefinition-java.lang.Class-
visit the link and there you will find it.

#Autowire
MongoTemplate mongoTemplate;
Query query = new Query();
Criteria filterCriteria = Criteria.where("bac").is("def");
query.addCriteria(filterCriteria);
Update update = new Update();
update.set("status", status);
mongoTemplate.updateMulti(query, update, MyClass.class);

Related

Java - Insert/Update with MongoDB collection bulkWrite

I am very new to MongoDB. Trying to understand the best option to perform Bulk Write in MongoDB. I want to periodically refresh my Application collection. The key's for documents are AppID, AppName and AppStatus.
Below are the actions I want to perform in every run -
Find the AppID in Application collection.
If not exists, perform an insert
If exists, only update the value of AppStatus key.
List<Application> applist = getAppList(); // List contains All the Application
private final MongoClient mongoClient;
private final MongoTemplate mongoTemplate;
MongoCollection<Document> collection =
mongoTemplate.getDb().getCollection("Application");
collection.bulkWrite (????);
How do I loop over the appList and perform a bulk insert/update ?
You can use org.springframework.data.mongodb.core.BulkOperations to perform bulk update/insert/upsert/delete operations.
List<Application> applist = getAppList();
List<Pair<Query, Update>> updates = new ArrayList<>(applist.size());
applist.forEach(application -> {
Query query = Query.query(Criteria.where("AppID").is(application.getAppID()));
Update update = new Update();
update.set("AppID", application.getAppID());
update.set("AppName", application.getAppName());
update.set("AppStatus", application.getAppStatus());
updates.add(Pair.of(query, update));
});
BulkOperations bulkOperations = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, "Application");
bulkOperations.upsert(updates);
bulkOperations.execute();

How do you check if a collection is capped?

Before, using spring data mongo you could do something like mongoClient.getDB(db_name).getCollection(collection_name).isCapped(). But now the getDB is deprecated, you could still use it but there must be some other way to do it.
I tried doing mongoClient.getDatabase(db_name).getCollection(collection_name).some_function() but there is no similar function like isCapped() now.
You can achieve to find if a collection is capped by doing the following.
MongoTemplate mongoTemplate = new MongoTemplate(mongoClient(), getDatabaseName());
Document obj = new Document();
obj.append("collStats", "yourCollection");
Document result = mongoTemplate.executeCommand(obj);
result.getBoolean("capped")

MongoDB Morphia Update multi=true VS bulk update

I want to update 10,000 documents in a single web request. I intend to update only one field (which is indexed) in all the documents matched with some criteria with same value.
I see morphia 1.3.2 always set multi=true parameter in update call. Is it enough for updating 10,000 document? Or there are any bulk update functionality in morphia.
The following code should work for you.
Query<Entity> query = datastore.createQuery(Entity.class);
query.filter("name = ", "xxx");
UpdateOperations<Entity> updateOperations = datastore.createUpdateOperations(Entity.class).set
("yyy", 200);
UpdateResults updateResults = datastore.update(query, updateOperations, false, null);
All the documents in the collection with name = 'xxx' will now have all their 'yyy' attribute equal to 200.

spring-data mongodb exclude fields from update

How to make sure that specific fields can be inserted upon creation, but can optionally be excluded when updating the object.
I'm essentially looking for something like the following:
mongoOperations.save(theObject, <fields to ignore>)
From what I see, recently introduced #ReadOnlyProperty will ignore the property both for inserts and updates.
I was able to get the desired behavior by implementing my Custom MongoTemplate and overriding its doUpdate method as follows:
#Override
protected WriteResult doUpdate(String collectionName, Query query,
Update originalUpdate, Class<?> entityClass, boolean upsert, boolean multi) {
Update updateViaSet = new Update();
DBObject dbObject = originalUpdate.getUpdateObject();
Update filteredUpdate = Update.fromDBObject(dbObject, "<fields to ignore>");
for(String key : filteredUpdate.getUpdateObject().keySet()){
Object val = filteredUpdate.getUpdateObject().get(key);
System.out.println(key + "::" + val);
updateViaSet.set(key, filteredUpdate.getUpdateObject().get(key));
}
return super
.doUpdate(collectionName, query, updateViaSet, entityClass, upsert, multi);
}
But the issue is that now it will use Mongo $set form of updates for everything, not just for specific cases.
Please advise if there is any simpler (and correct) way to achieve this.
While creating an update object, use $setOnInsert instead of $set. It is available in spring mongo as well.
If an update operation with upsert: true results in an insert of a document, then $setOnInsert assigns the specified values to the fields in the document. If the update operation does not result in an insert, $setOnInsert does nothing.

How do I query "Timestamp() or Date()" with MongoTemplate to MongoDB?

I use MongoTemplate to handle MongoDB
I want update documents' column to current time
In Mongodb command-line client, it will work with
db.collectionName.update({_id:1}, {timeCol: new Timestamp()});
or
db.collectionName.update({_id:1}, {timeCol: new Date()});
But I don't know how I do that by using mongoTemplate.
Update update;
update.set("timeCol", "new Timestamp()"); // of course, it doesn't work
Plz help me
Update Collection like this from Spring-data-mongodb 1.6 version, this will use MongoDb current Date
Query query = new Query();
query.addCriteria(Criteria.where("_id").is(1));
Update update = new Update();
update.currentDate("timeCol")
mongoOperations.updateFirst(query, update, "collectionName");
If you want Timestamp use update.currentTimestamp(key); instead of update.currentDate(key)
Build current timestamp as
Date currentDate = new Date();
Timestamp timeStamp = new Timestamp(currentDate.getTime());
Then update collection like this :
Query query = new Query();
query.addCriteria(Criteria.where("_id").is(1));
Update update = new Update();
update.set("timeCol", timeStamp);
mongoOperations.updateFirst(query, update, "collectionName");