Bulk Update with Spring Data MongoDB Reactive - spring-data

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

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

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

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 : 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.

Capped collections using MongoDB and SpringData

I am trying to create a capped collection for logging using mongoTemplate. However my collection size is growing beyond the size I passed as arguments. Can anyone please help with this.
public synchronized MongoTemplate getTemplate() {
if (template == null) {
Mongo mongo = null;
mongo = new Mongo(addrs);
template = new MongoTemplate(mongo, this.dbName);
if(!template.collectionExists(HttpRequestEntity.class)){
CollectionOptions options = new CollectionOptions(4,4,true);
template.createCollection(HttpRequestEntity.class, options);
}
}
return template;
}
For saving I am calling save on this template instance
getTemplate().save(entity);
Got it working after I deleted the collection from mongo console. I guess it was use old meta data as template.collectionExists(HttpRequestEntity.class) was returning true.