2014-01-24 6 views
1

У меня есть пользовательский объект следующим образом:Добавить набор строк в существующий набор с касбы

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

Я хочу, чтобы добавить набор строк в поле квитанций. Вот моя попытка сделать это с помощью одного обновления:

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

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

Когда я запускаю этот код я получаю встроенный набор следующим образом:

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

но результат я хочу:

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

Я могу заставить его работать, вызывая обновление для каждого элемента в toBeAcked, есть ли способ сделать это за один звонок?

ответ

4

Проблема заключается в том, что $each принимает переменное количество аргументов, а не тип коллекции, такой как Traversable. Из-за этого он рассматривает набор, который вы передаете как один элемент, и добавляет его в массив как таковой. Это приводит к гнездовью, как вы наблюдаете. Вам необходимо развернуть его таким образом: $each(toBeAcked: _*) или передать каждый элемент отдельно $each("x", "y", "z").

Вот полный пример, который работает, как вы ожидали бы это:

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() 
} 
+1

Спасибо. Это имеет смысл. Я не смогу попробовать это до понедельника. Тогда я выберу свой ответ. –

+1

Работал как шарм. Я не помню, чтобы в Scala было обозначено (x: _ *). Я узнал что-то новое. Благодарю. –

+1

Для меня это похоже на ошибку API, потому что вы действительно не хотите передавать один элемент в '$ each'. Вы хотели бы передать коллекцию. Поэтому было бы более ясным изменить подпись '$ each', чтобы взять коллекцию вместо этого. Возможно, это то, что вы ожидали, и он с радостью принял ваш аргумент как один элемент - немного запутывающий API, на мой взгляд. Я не думаю, что Scala API для MongoDB должен точно следовать синтаксису MongoDB. Я думаю, что это так, когда он должен расходиться. –