Frage

I have a user object as follows:

{ user: "joe", acks: ["a", "b" ] }

I want to add a set of strings to the acks field. Here's my attempt to do this with one update:

def addSomeAcks(toBeAcked = Array[String])
    DB.getCollection("userAcks").update(
        MongoDBObject("user" -> "joe"), 
        $addToSet("acks") $each toBeAcked  
    )
}

def test() {
   addSomeAcks(Set("x", "y", "z"))
}

When I run this code I get an embedded set as follows:

{ user: "joe", acks: ["a", "b", ["x", "y", "z" ] ] }

but the result I want is:

{ user: "joe", acks: ["a", "b", "x", "y", "z" ] }

I can make it work by calling update for each item in toBeAcked, is there a way to do this in one call?

War es hilfreich?

Lösung

The problem is that $each takes a variable number of arguments, not a collection type like Traversable. Because of that it treats the set that you pass as a single element and adds it to array as such. This leads to nesting as you observe. You need to unwrap it this way: $each(toBeAcked: _*) or pass each elem separately $each("x", "y", "z").

Here is a complete example that works as you'd expect it to:

package com.example

import com.mongodb.casbah.Imports._

object TestApp extends App {

  val col = MongoConnection()("test")("userAcks")

  def printAll(): Unit =
    col.find().foreach(println)

  def insertFirst(): Unit =
    col.insert(MongoDBObject("user" -> "joe", "acks" -> List("a", "b")))

  def addSomeAcks(toBeAcked: Seq[String]): Unit =
    col.update(
      MongoDBObject("user" -> "joe"),
      $addToSet("acks") $each (toBeAcked: _*))

  printAll()
  insertFirst()
  printAll()
  addSomeAcks(Seq("x", "y", "z"))
  printAll()
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top