summerNight
summerNight

Reputation: 1496

How to update a document using ReactiveMongo

I get the following list of documents back from MongoDB when I find for "campaignID":"DEMO-1".

[
  {
    "_id": {
      "$oid": "56be0e8b3cf8a2d4f87ddb97"
    },
    "campaignID": "DEMO-1",
    "revision": 1,
    "action": [
      "kick",
      "punch"
    ],

    "transactionID": 20160212095539543
  },
  {
    "_id": {
      "$oid": "56c178215886447ea261710f"
    },
    "transactionID": 20160215000257159,
    "campaignID": "DEMO-1",
    "revision": 2,
    "action": [
      "kick"
    ],
    "transactionID": 20160212095539578
  }
]

Now, what I am trying to do here is for a given campaignID I need to find all its versions (revision in my case) and modify the action field to dead of type String. I read the docs and the examples they have is too simple not too helpful in my case. This is what the docs say:

val selector = BSONDocument("name" -> "Jack")

val modifier = BSONDocument(
  "$set" -> BSONDocument(
    "lastName" -> "London",
    "firstName" -> "Jack"),
    "$unset" -> BSONDocument(
      "name" -> 1))

// get a future update
val futureUpdate = collection.update(selector, modifier)

I can't just follow the docs because its easy to create a new BSON document and use it to modify following the BSON structure by hardcoding the exact fields. In my case I need to find the documents first and then modify the action field on the fly because unlike the docs, my action field can have different values.

Here's my code so far which obviously does not compile:

def updateDocument(campaignID: String) ={
    val timeout = scala.concurrent.duration.Duration(5, "seconds")
    val collection = db.collection[BSONCollection](collectionName)
    val selector = BSONDocument("action" -> "dead")
    val modifier = collection.find(BSONDocument("campaignID" -> campaignID)).cursor[BSONDocument]().collect[List]()
    val updatedResults = Await.result(modifier, timeout)
    val mod = BSONDocument(
      "$set" -> updatedResults(0),
      "$unset" -> BSONDocument(
        "action" -> **<???>** ))
    val futureUpdate = collection.update(selector, updatedResults(0))
    futureUpdate
  }

Upvotes: 1

Views: 2705

Answers (2)

summerNight
summerNight

Reputation: 1496

This worked for me as an answer to my own question. Thanks @cchantep for helping me out.

val collection = db.collection[BSONCollection](collectionName)
val selector = BSONDocument("campaignID" -> campaignID)
val mod = BSONDocument("$set" -> BSONDocument("action" -> "dead"))
val futureUpdate = collection.update(selector, mod, multi = true)

Upvotes: 6

cchantep
cchantep

Reputation: 9168

If you have a look at the BSON documentation, you can see BSONArray can be used to pass sequence of BSON values.

BSONDocument("action" -> BSONArray("kick", "punch"))

If you have List[T] as values, with T being provided a BSONWriter[_ <: BSONValue, T], then this list can be converted as BSONArray.

BSONDocument("action" -> List("kick", "punch"))
// as `String` is provided a `BSONWriter`

Upvotes: 2

Related Questions