Предположим, у нас есть следующая коллекция, о которой у меня есть несколько вопросов:
{
"_id" : ObjectId("4faaba123412d654fe83hg876"),
"user_id" : 123456,
"total" : 100,
"items" : [
{
"item_name" : "my_item_one",
"price" : 20
},
{
"item_name" : "my_item_two",
"price" : 50
},
{
"item_name" : "my_item_three",
"price" : 30
}
]
}
1 - я хочу увеличить цену для "item_name": "my_item_two" и, если она не существует , она должна быть добавлена в массив "items".
2 - Как я могу обновить два поля одновременно. Например, увеличьте цену на «my_item_three» и одновременно увеличьте «итого» (с тем же значением).
Я предпочитаю делать это на стороне MongoDB, в противном случае я должен загрузить документ на стороне клиента (Python), создать обновленный документ и заменить его на существующий в MongoDB.
ОБНОВЛЕНИЕ Это то, что я пытался и работает нормально, если объект существует :
db.test_invoice.update({user_id : 123456 , "items.item_name":"my_item_one"} , {$inc: {"items.$.price": 10}})
Но если ключ не существует, он ничего не делает. Также он только обновляет вложенный объект. Эта команда также не может обновить поле «итого».
Ответы:
Для вопроса № 1 давайте разберем его на две части. Сначала увеличьте любой документ, у которого "items.item_name" равен "my_item_two". Для этого вам нужно использовать позиционный оператор «$». Что-то вроде:
Обратите внимание, что это будет только увеличивать первый подобранный вложенный документ в любом массиве (поэтому, если у вас есть другой документ в массиве с «item_name», равным «my_item_two», он не будет увеличен). Но это может быть то, что вы хотите.
Вторая часть сложнее. Мы можем поместить новый элемент в массив без my_item_two следующим образом:
На ваш вопрос № 2 ответ проще. Чтобы увеличить сумму и цену item_three в любом документе, содержащем «my_item_three», вы можете использовать оператор $ inc для нескольких полей одновременно. Что-то вроде:
источник
Нет способа сделать это в одном запросе. Вы должны искать документ в первом запросе:
Если документ существует:
еще
Нет необходимости добавлять условия
{$ne : "my_item_two" }
.Также в многопоточной среде вы должны быть осторожны, чтобы только один поток мог выполнить второй (вставить регистр, если документ не был найден) за один раз, в противном случае будут вставлены дубликаты для вставки документов.
источник
Мы можем использовать
$set
оператор для обновления вложенного массива в объекте поданного обновления значенияисточник