Как правильно сделать апсерт с помощью ReactiveMongo

Предположим, у меня есть эта запись в коллекции:

{
    "_id" : ObjectId("5c56160e4b6929067972b4c8"),
    "name" : "car",
    "attributes" : [
        {
            "color" : "blue",
            "qty" : 10
        }
    ]
}

Код, который я реализовал для upsert, выглядит следующим образом:

  def insert(item: Item): Future[Option[Item]] = {
    val selector = BSONDocument("name" -> item.name, "attributes" -> BSONDocument("$elemMatch" -> Json.toJson(item.attributes.head)))

    val updateModifier = BSONDocument(
      f"$$push" -> BSONDocument("attributes" -> Json.toJson(item.attributes.head)))

    itemsCollection.flatMap(
      _.findAndUpdate(selector, updateModifier, upsert = true)
        .map(_.result[Item])
    )
  }

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

{
    "_id" : ObjectId("5c56160e4b6929067972b4c8"),
    "name" : "car",
    "attributes" : [
        {
            "color" : "blue",
            "qty" : 10
        },
        {
            "color" : "blue",
            "qty" : 10
        }
    ]
}

Обратите внимание, что добавляется повторяющаяся запись. Этого не должно происходить согласно логике upsert.

Как я могу предотвратить вставку повторяющейся записи? Что не так с кодом?

Сначала попробуйте в mongoshell

cchantep 03.02.2019 00:21

После консультации с людьми на канале MongoDB, по-видимому, это НЕ тривиальная вещь, т.е. вставка во встроенный документ. Mongo — безумно сложный инструмент для работы, когда документ имеет хотя бы намек на сложность. Плоские документы в порядке. Результирующие запросы просты. Но как только структура данных становится сложной, запросы становятся очень сложными для написания.

M.K. 03.02.2019 20:33
Использование JavaScript и MongoDB
Использование JavaScript и MongoDB
Сегодня я собираюсь вкратце рассказать о прототипах в JavaScript, а также представить и объяснить вам работу с базой данных MongoDB.
0
2
336
0

Другие вопросы по теме