Java - Insert/Update with MongoDB collection bulkWrite - mongodb

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

Related

Bulk Update with Spring Data MongoDB Reactive

How can I perform bulk perations using ReactiveMongoTemplate?
Basically I want to initialize bulk using db.<collection_name>.initializeUnorderedBulkOp() and execute it using <bulk>.execute().
I know there is a way to do this using simple MongoTemplate as specified here but I can't find any way how to do this in reactive.
I finally managed to perform bulk writing using MongoCollection.bulkWrite method.
reactiveMongoTemplate.getCollection("assets_refs").flatMap(mongoCollection -> {
var operations = entities.stream().map(entity -> {
Document doc = new Document();
reactiveMongoTemplate.getConverter().write(entity, doc);
var filter = new Document("externalId", entity.getExternalId());
return new UpdateOneModel<Document>(filter, new Document("$set", doc), new UpdateOptions().upsert(true));
}).toList();
return Mono.from(mongoCollection.bulkWrite(operations));
})

update multiple documents in mongodb from spring mongo

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

Complex mongodb query with Quarkus

I need to migrate a Spring Boot project to Quarkus. The project has been using Spring Data Mongodb for all the queries. Now I find it difficult to migrate complex queries.
One example is
public List<MyData> findInProgressData(MyConditions conditions) {
Query mongoQuery = new Query();
mongoQuery.addCriteria(Criteria.where("status").is(IN_PROGRESS));
mongoQuery.addCriteria(Criteria.where("location").is(conditions.getLocationCode()));
if (StringUtils.isNotBlank(conditions.getType())) {
mongoQuery.addCriteria(Criteria.where("type").is(conditions.getType()));
}
if (StringUtils.isNotBlank(conditions.getUserId())) {
mongoQuery.addCriteria(Criteria.where("userId").is(conditions.getUserId()));
}
mongoQuery.with(Sort.by(Sort.Direction.ASC, "createdAt"));
return mongoTemplate.find(mongoQuery, MyData.class);
}
How can I implement the conditional query with Quarkus?
You can probably try Panache with Mongodb.
You can pass Document into .find() method, In this object you can specify any criteria.
final Document document = new Document();
document.put("status","IN_PROGRESS");
...
result = MyData.find(document); // or MyDataRepository
But you'll need to adapt some of the code to Panache, which can be done either via extending PanacheEntity or PanacheEntityBase

MongoDB : How to find multiple documents and update at the same time?

I have mongo DB and I am using C#.Net to interact with mongo db. C# API has methods for finding a single document and updating it at the same time. For example FindOneAndUpdateAsync.
However I couldn't find any method to find multiple documents and update them at the same time asynchronously.
The code below finding and processing each document asynchronously. How do I also update that document at the same time?
public async Task<IList<IDictionary<string, string>>> DoWork()
{
var collection = _mongoDatabase.GetCollection<BsonDocument>("units");
var filterBuilder = Builders<BsonDocument>.Filter;
var filter = filterBuilder.Ne<string>("status", "INIT") &
(filterBuilder.Exists("isDone", false) |
filterBuilder.Eq<bool>("isDone", false));
// I want to pass this update filter to update the document. But not sure how
var update = Builders<BsonDocument>.Update
.CurrentDate("startTime");
var sort = Builders<BsonDocument>.Sort.Ascending("startTime");
var projection = Builders<BsonDocument>.Projection
.Include("_id")
.Include("fileName"); // for bravity i have removed other projection elements
var output = new List<IDictionary<string, string>>();
// How do i pass update filter and update the document at the same time??
await collection
.Find(filter)
.Sort(sort)
.Project(projection)
.ForEachAsync((unit) =>
{
var dictionary = new Dictionary<string, string>();
Recurse(unit, dictionary);
output.Add(dictionary);
});
return output.Count > 0 ? output : null;
}
That doesn't exist in the mongo .Net api see here.
Just use a combination of Find and UpdateManyAsync.

MongoDB udate query using class object in C#?

I am storing class object in mongodb like below,
try
{
Sample risk = new Sample();
risk.Name = "ABC";
risk.Enable = true;
risk.Sender = "IBM";
risk.Target = "CITI";
MongoServer server = MongoServer.Create("mongodb://localhost");
MongoDatabase db = server.GetDatabase("DATABASE");
db.GetCollection<StockQuote>("SMAPLETABLE").Insert(risk);
}
catch (Exception e)
{
MessageBox.Show("Error");
}
now i want to to update that same class instance like db.GetCollection<StockQuote>("SMAPLETABLE").Insert(risk); how can i do this one.
There is two approaches two update document:
1.Via Save method and update etire document
db.GetCollection<StockQuote>("SMAPLETABLE").Save(risk);
2.Via atomic update: update part of document. For example if you need update Enable field of document with Name "ABC":
db.GetCollection<StockQuote>("SMAPLETABLE").Update(
Query.EQ("Name", "ABC"),
Update.Set("Enable", false));
Some notes:
With atomic updates you can avoid concurrency issues. Atomic update it is like transaction within one document.