How to upsert document in MongoDB Java driver 3

12,907

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)
)
Share:
12,907

Related videos on Youtube

rmin
Author by

rmin

Polyglot programmer specialising in Scala.

Updated on May 16, 2022

Comments

  • rmin
    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 of DBObject 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
    rmin almost 9 years
    thanks 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 returns AcknowledgedUpdateResult{matchedCount=0, modifiedCount=null, upsertedId=null} and has no effect on the database.
  • Ross
    Ross almost 9 years
    Make 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
    rmin almost 9 years
    Thanks 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.