Вставьте новые документы или измените поле массива существующего документа

Извините, если это повторная публикация, но я не смог получить нужный запрос из примеров документации mongodb.

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

Я могу использовать findOne() с некоторой условной логикой и, вероятно, решить эту проблему, но я думаю, что в mongodb есть реализация этого варианта использования.

Вот код на данный момент:

#data_json = JSON document to be added to collection

collection.update_one({"json_id":data_json["json_id"], "_dashbd_id_":dashboard_id},{{"$addToSet": {"array_field":keyword}},{"$setOnInsert":data_json}}, upsert=True)

Я запрашиваю json_id и _dashbd_id_ из моей коллекции. Если он существует, то я намерен добавить «ключевое слово» в поле array_field. Если он не существует, создайте новый документ как data_json, который включает array_field = [ключевое слово]

Любые подсказки и предложения приветствуются!


person cynical biscuit    schedule 30.01.2016    source источник
comment
Как вы думаете, зачем вам нужен $setOnInsert ? Ваш запрос неясен. Не могли бы вы уточнить?   -  person styvane    schedule 31.01.2016
comment
setOnInsert для добавления документа в коллекцию, если он не существует (иначе не найдено совпадений с заданными json_id и dashbd_id )   -  person cynical biscuit    schedule 31.01.2016


Ответы (2)


Если я правильно вас понял, вы хотите обновлять значения в базе данных, только если они не существуют, а также создавать новые документы с массивами в них. Хорошо, в mongodb есть способ, о котором я упомяну в этом ответе. Я думаю, что вы должны сначала знать несколько команд, которые помогут вам достичь аналогичного результата (опять же, есть простой способ, просто прочитайте дальше)

Начну с первой части:

чтобы обновить элемент в массиве, вы используете точечную нотацию для примера индекса:

db.collection_name.update({"_id": id}, {'$set': {"array_name.indexNumber": value}})

скажем, у нас есть следующий документ в названии коллекции cars

db.cars.findOne():
{
 _id: 1
 name: EvolutionX
 brand: Mitsubish
 year: 2012
 mods: [ turbo, headlights ] 
}

Скажем, в приведенном выше примере мы хотим обновить фары с помощью задних фонарей, мы делаем следующее (используя mongoshell, вы можете опускать кавычки в именах клавиш, Нет когда используя индекс массива):

db.cars.update({id:1}, {$set:{"mods.1":"rearlights"}})

1 – индекс фар.

Обратите внимание и будьте осторожны: если вы не использовали индекс внутри массива, например

db.cars.update({id:1}, {$set:{"mods":"rearlights"}})

это перезапишет существующий документ _id:1 и потеряет все остальные атрибуты или поля внутри документа, что приведет к следующему:

db.cars.findOne():
{
 _id: 1
 mods: [ rearlights ] 
}

Теперь предположим, что мы хотим добавить элемент tires в массив mods. Вы можете использовать $push как:

db.collection_name.update({"_id": id}, {'$push': {"array_name": value}})

так и будет

db.cars.update({"_id":1}, {"$push":{"mods":"tires"}})

теперь скажите, что вместо обновления массива mods вы хотите удалить "фары". В этом случае вы используете $pop

db.cars.update({"_id":1}, {"$pop":{"mods":"headlights"}})

Теперь с учетом этого. Простой способ: в mongodb для добавления в массив, только если элемент не существует, вы можете использовать $addToSet. Мне нравится этот оператор, потому что он добавит массив только в том случае, если элемент не существует. Вот как это использовать:

db.cars.update({"_id":1}, {"$addToSet":{"mods":"headlights"}})

Теперь, если фары есть в массиве, они не будут добавлены, иначе они будут добавлены в конец массива.

Хорошо, это первая часть вопроса. Вторая часть, которая инициализирует документ массивом. Хорошо, здесь есть две мысли: во-первых, вам не нужно. используя addToSet, вы можете создать массив, если он не существует (при условии, что _id 2 существует, но без модов множество):

db.cars.update({"_id":2}, {"$addToSet":{"mods":"bonnet"}})

Это создаст массив, если документ _id:2 существует. Предполагая, что _id:3 не существует, вам нужно будет подключить третий атрибут с именем upsert.

db.cars.update({"_id":3}, {"$addToSet":{"mods":"headlights"}}, {upsert:true})

это создаст третий документ с массивом mods с фарами внутри него и _id:3. Обратите внимание, что никакие другие атрибуты не будут добавлены, только массив _id и mods.

вторая мысль: когда вы вставляете новый документ, вы вставляете его с пустым массивом mods как mod:[] Надеюсь, это поможет

person ibininja    schedule 31.01.2016
comment
Спасибо ibininja за этот информативный пост! Я думаю, что был жадным и хотел выполнить действие в одном запросе монго, а не в двух. В итоге я сделал оператор if/else и выяснил, что мне нужно. Спасибо за ваши предложения - person cynical biscuit; 31.01.2016

предположим, что ваши data_json, dashboard_id и ключевое слово содержат следующую информацию.

   dashboard_id = ObjectId("5423200e6694ce357ad2a1ac")
   keyword = "testingKeyword"
   data_json = 
   {  
           "json_id":ObjectId("5423200e6694ce357ad2a1ac"),   
           "item":"EFG222",  
           "reorder":false,  
   }

если вы выполните запрос ниже

db.collection_name.update({"json_id":data_json["json_id"], "_dashbd_id_":dashboard_id},{{"$addToSet": {"array_field":keyword}},{ upsert=True}) 

чем он будет помещать ключевое слово в array_field, если документ существует, или вставлять новый документ со следующей информацией, как показано ниже.

     {  
           "_id":ObjectId("5sdvsdv6sdv694ce357ad2a1ac"),
           "json_id":ObjectId("5423200e6694ce357ad2a1ac"),
           "dashboard_id": ObjectId("sddfb6694ce357ad2a1ac")
           "item":"EFG222",  
           "reorder":false,  
           "array_field":
              [                    
              "testingKeyword"
           ]
 }
person Brijesh Patel    schedule 31.01.2016