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 }), но как решить проблему без использования индексов??

Что не так??


person alberto adami    schedule 28.10.2014    source источник


Ответы (1)


То, что вы хотите сделать, это обновление на месте. Чтобы сделать это с ReactiveMongo, вам нужно использовать оператор обновления, чтобы указать, какой поля для обновления и как. Вместо этого вы передали correlation (который, как я полагаю, является своего рода BSONDocument) методу обновления коллекции. Это просто запрашивает замену документа, что, если значение уникального индекса отличается, приведет к добавлению нового документа в коллекцию. Вместо передачи correlation вы должны передать BSONDocument, который использует один из операторов обновления например, $set (установка поля) или $incr (увеличение числового поля на единицу). Подробнее о том, как это сделать, см. в документации MongoDB, Modify Document

person Reid Spencer    schedule 28.10.2014