Asumsikan kita memiliki koleksi berikut, yang saya punya beberapa pertanyaan tentang:
{
"_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 - Saya ingin menaikkan harga untuk "item_name": "my_item_two" dan jika tidak ada , itu harus ditambahkan ke array "items".
2 - Bagaimana saya bisa memperbarui dua bidang sekaligus. Misalnya, naikkan harga untuk "my_item_three" dan pada saat yang sama naikkan "total" (dengan nilai yang sama).
Saya lebih suka melakukan ini di sisi MongoDB, kalau tidak saya harus memuat dokumen di sisi klien (Python) dan membangun dokumen yang diperbarui dan menggantinya dengan yang ada di MongoDB.
UPDATE Ini adalah apa yang saya coba dan berfungsi dengan baik JIKA ADA Objek Ada :
db.test_invoice.update({user_id : 123456 , "items.item_name":"my_item_one"} , {$inc: {"items.$.price": 10}})
Tetapi jika kuncinya tidak ada itu tidak melakukan apa-apa. Juga hanya memperbarui objek bersarang. Tidak ada cara dengan perintah ini untuk memperbarui bidang "total" juga.
Jawaban:
Untuk pertanyaan # 1, mari kita bagi menjadi dua bagian. Pertama, tambahkan dokumen apa pun yang memiliki "items.item_name" sama dengan "my_item_two". Untuk ini, Anda harus menggunakan operator "$" posisional. Sesuatu seperti:
Perhatikan bahwa ini hanya akan menambah subdokumen yang cocok pertama dalam array apa pun (jadi jika Anda memiliki dokumen lain dalam array dengan "item_name" sama dengan "my_item_two", itu tidak akan bertambah). Tapi ini mungkin yang Anda inginkan.
Bagian kedua lebih rumit. Kami dapat mendorong item baru ke array tanpa "my_item_two" sebagai berikut:
Untuk pertanyaan Anda # 2, jawabannya lebih mudah. Untuk menambah total dan harga item_three dalam dokumen apa pun yang berisi "my_item_three," Anda dapat menggunakan operator $ inc pada banyak bidang sekaligus. Sesuatu seperti:
sumber
Tidak ada cara untuk melakukan ini dalam permintaan tunggal. Anda harus mencari dokumen di kueri pertama:
Jika ada dokumen:
Lain
Tidak perlu menambahkan kondisi
{$ne : "my_item_two" }
.Juga dalam lingkungan multithreaded Anda harus berhati-hati bahwa hanya satu utas yang dapat mengeksekusi yang kedua (masukkan case, jika dokumen tidak ditemukan) pada suatu waktu, jika tidak, dokumen duplikat embed akan dimasukkan.
sumber
Kita dapat menggunakan
$set
operator untuk memperbarui array bersarang di dalam objek yang diajukan, memperbarui nilaisumber