How to upsert document in MongoDB Java driver 3
In the Mongo Java Driver 3.0 series we added a new Crud API which is more explicit and therefore beginner friendly. This initiative has been rolled out over a number of MongoDB Drivers but it does contain some changes compared to the older API.
As you are not updating an existing document using an update operator, the updateOne
method is not appropriate.
The operation you describe is a replaceOne
operation and can be run like so:
sessionCollection.replaceOne(
"_id" -> new BsonString(sessionKey),
sessionDocument,
(new UpdateOptions()).upsert(true)
)
Related videos on Youtube
Comments
-
rmin almost 2 years
what is the idiomatic way to upsert a document using version 3 of the mongodb java driver (specifically v3.0.1)?
We have a collection for sessions and when a new session gets created or modified, we want to upsert it in one operation - rather than having to query if a document exists yet and then either inserting or replacing.
Our old upsertion code used the scala driver casbah 2.7.3. It looked like:
import com.mongodb.casbah.MongoCollection import com.mongdb.DBObject val sessionCollection: MongoCollection = ... val sessionKey: String = ... val sessionDocument: DBObject = ... // Either create a new one, or find and modify an existing one sessionCollection.update( "_id" -> sessionKey, sessionDocument upsert = true )
In our current project we're just using the plain java 3.0.1 driver and we're using
BsonDocument
instead ofDBObject
to make it more typsafe. I tried to replace the above with something like:import com.mongodb.client.MongoCollection val sessionCollection: MongoCollection = ... val sessionKey: String = ... val sessionDocument: BsonDocument = // Either create a new one, or find and modify an existing one val updateOptions = new UpdateOptions updateOptions.upsert(true) sessionCollection.updateOne( "_id" -> new BsonString(sessionKey), sessionDocument, updateOptions )
This throws the error "java.lang.IllegalArgumentException: Invalid BSON field name ...". The error is covered in this question but the op in that question wasn't trying to upsert in one operation - they were using context to decide whether to replace/update/insert etc...
I'm happy with code samples in scala or java.
Thanks!
-
rmin almost 9 yearsthanks for the help. I think though what you're suggesting is not what I'm after. I want an operation that inserts a new session if none exists with that id, or updates the existing session if it does exist (ie. an "upsertion").
replaceOne
only does the latter. When I use your code snippet to try and insert a fresh session in the database, it naturally returnsAcknowledgedUpdateResult{matchedCount=0, modifiedCount=null, upsertedId=null}
and has no effect on the database. -
Ross almost 9 yearsMake sure you set the upserted in the updateOptions, I've clarified the example. As you aren't updating via an update operator, but rather are doing an upsert replace then you need the
replaceOne
method. -
rmin almost 9 yearsThanks Ross! It works now. If your answer is meant to be scala code, can you put brackets around
new UpdateOptions
- ie. change it to(new UpdateOptions).upsert(true)
. Otherwise it doesn't compile.