Использование $ pu sh для нулевого массива - PullRequest
1 голос
/ 12 июля 2020

У меня есть документ mon go, в котором есть поле массива с именем «events».

Это поле иногда может быть пустым.

Я использую $push для добавления элемента в массив «событий». Проблема в том, что он не может работать, когда поле «события» имеет значение null

Например, если в базе данных это выглядит так:

{
"_id" : ObjectId("4d2d8deff4e6c1d71fc29a07"),
"user_id" : "714638ba-2e08-2168-2b99-00002f3d43c0",
"events" : null
 }

и я запускаю Update с помощью $ pu sh:

{ $push : { "events" : { "profile" : 10, "data" : "X"}}};

он завершится ошибкой, потому что событие равно нулю.

Я могу исправить это, выполнив 2 шага запроса базы данных. Но могу ли я сделать это в 1 запросе?

Я хочу добавить событие в массив, если поля массива не равны нулю, но если оно равно нулю, сначала создайте пустой массив «событий» и позже добавим событие в массив.

Ответы [ 2 ]

1 голос
/ 13 июля 2020

Начиная с MogoDB 4.2, вы можете использовать Обновления с конвейером агрегации . Это позволяет выполнять обновление как одну операцию.

var OBJ_TO_ADD = { "profile": 10, "data": "X" }

db.test.updateOne(
  { "_id" : ObjectId("4d2d8deff4e6c1d71fc29a07") }, 
  [ 
      { 
          $set: { 
              events: { 
                  $ifNull: [ 
                      { $concatArrays: [ "$events", [ OBJ_TO_ADD ] ] }, 
                      [ OBJ_TO_ADD ] 
                  ] 
              }
          }
      } 
  ] 
)
1 голос
/ 12 июля 2020

Не записывайте нулевые значения для полей, в которых нет данных. Тогда вы сможете использовать $ pu sh ожидаемым образом:

MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.insert({a:1})
WriteResult({ "nInserted" : 1 })
MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.update({a:1},{$push:{b:[1]}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.find()
{ "_id" : ObjectId("5f0b481dd9c782d95389a1ce"), "a" : 1, "b" : [ [ 1 ] ] }

Если вы настаиваете на записи нулей в базу данных, вы можете использовать обновление конвейера агрегации с помощью $ set, $ ifNull, $ concatArrays и $ merge:

MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.insert({a:2,b:null})
WriteResult({ "nInserted" : 1 })
MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.find()
{ "_id" : ObjectId("5f0b4bfbd9c782d95389a1d2"), "a" : 2, "b" : null }
MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.aggregate([{$match:{a:2}},{$set:{b:{$ifNull:[{$concatArrays:['$b',[4]]},[4]]}}},{$merge:'foo'}])
MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.find()
{ "_id" : ObjectId("5f0b4bfbd9c782d95389a1d2"), "a" : 2, "b" : [ 4 ] }
MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.aggregate([{$match:{a:2}},{$set:{b:{$ifNull:[{$concatArrays:['$b',[5]]},[5]]}}},{$merge:'foo'}])
MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.find()
{ "_id" : ObjectId("5f0b4bfbd9c782d95389a1d2"), "a" : 2, "b" : [ 4, 5 ] }
...