Java MongoDB save multiple documents at once
Asked Answered
C

5

6

I Have a list of updated objects/documents i need save all the objects in the list at once.

I saw save() in MongoTemplate but it can take single document at a time. Is there any way to save multiple documents at once or i need to call save in loop ?

Cagliostro answered 6/6, 2018 at 11:7 Comment(2)
have you tried insertAll()Scalpel
@Scalpel insertAll() is for new documents but i need to update if the document exists or insert if its doesn't existsCagliostro
U
5

You can use insertAll of MongoTemplate or ReactiveMongoTemplate, but you have to use it with caution. It does what it's name stands for - it inserts all documents. If you call save method then the save has optimistic locking, so it checks if you don't override the document that you shouldn't (if it has the @Version annotation). insertAll doesn't check for optimistic locking so you can use it as long as you really want to do an insert e.g. persist documents that aren't persisted yet or you don't care about overriding those documents and optimistic locking. If you care about optimistic locking then all you can do is to call save for each document which will generate a lot of I/O operations, but that's what it takes to make sure that you will update documents with matching version. Also you have to remember that insertAll actually inserts new documents, meaning that you can't update document using this method, because you'll get duplicated key exception. Currently spring mongo lacks a feature that would allow to update all the documents (you can only 'insert' them, so save for the first time)

Unship answered 5/2, 2021 at 8:6 Comment(0)
C
3

Thanks for all the help.

I was able to do it using Spring data MongoDB. Spring data MongoDB's MongoRepository has many inbuilt methods.

org.springframework.data.mongodb.repository.MongoRepository.saveAll(Iterable entites) is the one which i used to save multiple documents.

Cagliostro answered 6/6, 2018 at 17:30 Comment(1)
Note that the default implementation of MongoRepository.saveAll() is SimpleMongoRepository.saveAll(), which fires off a separate request for every single update.Royo
B
1

Using Spring you can easily store multiple documents at once.

The Interface is already available with method saveAll and details as under:

@NoRepositoryBean
public interface MongoRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {

    /*
     * (non-Javadoc)
     * @see org.springframework.data.repository.CrudRepository#saveAll(java.lang.Iterable)
     */
    @Override
    <S extends T> List<S> saveAll(Iterable<S> entites);
//...
}

Spring usage example:

@Component
public class Processor {

@Autowired
public Processor(Repository repository) {
    this.repository= repository;
}

public void save(Iterable<ProductEntity> entites) {
    List<ProductEntity> saved = repository.saveAll(entites);
    logger.info("Saved {} entities", saved.size());
}

}

your Repository interface:

//https://docs.spring.io/spring-data/mongodb/docs/1.2.0.RELEASE/reference/html/mongo.repositories.html
public interface Repository extends MongoRepository<ProductEntity, String> {   
}

Call save method with 'List' of Product entities

Beauregard answered 12/9, 2018 at 11:3 Comment(0)
S
0

This is one way to do.

mongoTemplate.getCollection("your_collection_name").insert(List<Documents>)

You might want to check out BulkWriteOperation class as well.

Scalpel answered 6/6, 2018 at 11:13 Comment(0)
M
0

For Insert:

You should use the function InsertMany like:

List<Document> docList = new List<Document>();
docList.add(doc1); // assuming that doc1 and doc2 are defined
docList.add(doc2);
yourMongoDb.getCollection("your_collection").insertMany(docList);

For Upsert (what you need):

UpdateOptions options = new UpdateOptions().upsert(true) ;
yourCollectionOfDocuments.forEach( doc ->{ 
    Document filter = Filters.eq("_id", doc.get("id"));
    yourDb.getCollection("your_collection").updateOne(filter,update,option); 
})
Minstrelsy answered 6/6, 2018 at 11:19 Comment(2)
This solution is for new documents but i need update existing documentsCagliostro
I see. Then what you need is upsert: UpdateOptions options = new UpdateOptions().upsert(true); yourCollectionOfDocuments.forEach( doc ->{ Document filter = Filters.eq("_id", doc.get("id")) yourDb.getCollection("your_collection").updateOne(filter,update,option) }); Minstrelsy

© 2022 - 2024 — McMap. All rights reserved.