MongoDB обновляет документ, когда уже существует с ReactiveMongo
Я пишу веб-приложение Scala, которое использует MongoDB в качестве базы данных и ReactiveMongo в качестве драйвера.
У меня есть коллекция с именем recommendation.correlation
в котором я сохранил соотношение между продуктом и категорией.
Документ имеет следующую форму:
{ "_id" : ObjectId("544f76ea4b7f7e3f6e2db224"), "category" : "c1", "attribute" : "c3:p1", "value" : { "average" : 0, "weight" : 3 } }
Сейчас я пишу метод следующим образом:
def calculateCorrelation: Future[Boolean] = {
def calculate(category: String, tag: String, similarity: List[Similarity]): Future[(Double, Int)] = {
println("Calculate correlation of " + category + " " + tag)
val value = similarity.foldLeft(0.0, 0)( (r, c) => if(c.tag1Name.split(":")(0) == category && c.tag2Name == tag) (r._1 + c.eq, r._2 + 1) else r
) //fold the tags
val sum = value._1
val count = value._2
val result = if(count > 0) (sum/count, count) else (0.0, 0)
Future{result}
}
play.Logger.debug("Start Correlation")
Similarity.all.toList flatMap { tagsMatch =>
val tuples =
for {
i<- tagsMatch
} yield (i.tag1Name.split(":")(0), i.tag2Name) // create e List[(String, String)] containing the category and productName
val res = tuples map { el =>
calculate(el._1, el._2, tagsMatch) flatMap { value =>
val correlation = Correlation(el._1, el._2, value._1, value._2) // create the correlation
val query = Json.obj("category" -> value._1, "attribute" -> value._2)
Correlations.find(query).one flatMap(element => element match {
case Some(x) => Correlations.update(query, correlation) flatMap {status => status match {
case LastError(ok, _, _, _, _, _, _) => Future{true}
case _ => Future{false}
}
}
case None => Correlations.save(correlation) flatMap {status => status match {
case LastError(ok, _, _, _, _, _, _) => Future{true}
case _ => Future{false}
}
}
}
)
}
}
val result = if(res.exists(_ equals false)) false else true
Future{result}
}
Проблема в том, что метод вставки дублирует документы. Почему это случилось??
Я решил использовать db.recommendation.correlation.ensureIndex({"category": 1, "attribute": 1}, {"unique": true, "dropDups":true })
, но как я могу исправить проблему, не используя индексы??
В чем дело??
1 ответ
То, что вы хотите сделать, это обновление на месте. Чтобы сделать это с ReactiveMongo, вам нужно использовать оператор обновления, чтобы сообщить ему, какие поля обновлять и как. Вместо этого вы прошли correlation
(что я предполагаю, что-то вроде BSONDocument) для метода обновления коллекции. Это просто требует замены документа, что, если уникальное значение индекса отличается, приведет к добавлению нового документа в коллекцию. Вместо прохождения correlation
Вы должны передать BSONDocument, который использует один из операторов обновления, например, $set (установить поле) или $incr (увеличить числовое поле на единицу). Подробнее об этом см. В документации MongoDB, Изменить документ