Apa yang Anda coba lakukan di sini adalah menambahkan item baru ke array hanya di mana item tersebut tidak ada dan juga membuat dokumen baru di mana item tersebut tidak ada. Anda memilih $addToSet
karena Anda ingin item menjadi unik, tetapi sebenarnya Anda benar-benar ingin item tersebut unik hanya dengan "a".
Jadi $addToset
tidak akan melakukan itu, dan Anda lebih perlu "menguji" elemen yang ada. Tetapi masalah sebenarnya di sini adalah tidak mungkin untuk melakukan itu dan "memasukkan" pada saat yang bersamaan. Logika tidak dapat bekerja karena dokumen baru akan dibuat setiap kali elemen array tidak ditemukan, daripada menambahkan elemen array seperti yang Anda inginkan.
Kesalahan operasi saat ini dengan desain sebagai $addToSet
tidak dapat digunakan untuk "membuat" array, tetapi hanya untuk "menambahkan" anggota ke array yang ada. Tetapi seperti yang sudah dinyatakan, Anda memiliki masalah lain dalam mencapai logika.
Yang Anda butuhkan di sini adalah urutan operasi pembaruan yang masing-masing "mencoba" untuk melakukan tindakan yang diharapkan. Ini hanya dapat dilakukan dengan beberapa pernyataan:
// attempt "upsert" where document does not exist
// do not alter the document if this is an update
db.test.update(
{ "name": "abc" },
{ "$setOnInsert": { "config": [{ "a": 1, "b": 2 }] }},
{ "upsert": true }
)
// $push the element where "a": 1 does not exist
db.test.update(
{ "name": "abc", "config.a": { "$ne": 1 } },
{ "$push": { "config": { "a": 1, "b": 2 } }}
)
// $set the element where "a": 1 does exist
db.test.update(
{ "name": "abc", "config.a": 1 },
{ "$set": { "config.$.b": 2 } }
)
Pada iterasi pertama, pernyataan pertama akan "memasukkan" dokumen dan membuat larik dengan item. Pernyataan kedua tidak akan cocok dengan dokumen karena elemen "a" memiliki nilai yang ditentukan. Pernyataan ketiga akan cocok dengan dokumen tetapi tidak akan mengubahnya dalam operasi tulis karena nilainya tidak berubah.
Jika sekarang Anda mengubah input menjadi "b": 3
Anda mendapatkan tanggapan yang berbeda tetapi hasil yang diinginkan:
db.test.update(
{ "name": "abc" },
{ "$setOnInsert": { "config": [{ "a": 1, "b": 3 }] }},
{ "upsert": true }
)
db.test.update(
{ "name": "abc", "config.a": { "$ne": 1 } },
{ "$push": { "config": { "a": 1, "b": 3 } }}
)
db.test.update(
{ "name": "abc", "config.a": 1 },
{ "$set": { "config.$.b": 3 } }
)
Jadi sekarang pernyataan pertama cocok dengan dokumen dengan "name": "abc"
tetapi tidak melakukan apa-apa karena satu-satunya operasi yang valid adalah pada "insert". Pernyataan kedua tidak cocok karena "a" cocok dengan kondisi. Pernyataan ketiga cocok dengan nilai "a" dan mengubah "b" di elemen yang cocok ke nilai yang diinginkan.
Selanjutnya mengubah "a" ke nilai lain yang tidak ada dalam larik memungkinkan 1 dan 3 tidak melakukan apa-apa selain pernyataan kedua menambahkan anggota lain ke larik dengan menjaga konten tetap unik dengan kunci "a".
Juga mengirimkan pernyataan tanpa perubahan dari data yang ada tentu saja akan menghasilkan tanggapan yang mengatakan tidak ada yang berubah di semua akun.
Begitulah cara Anda melakukan operasi Anda. Anda dapat melakukannya dengan "dipesan" Bulk operasi sehingga hanya ada satu permintaan dan respons dari server dengan respons yang valid untuk diubah atau dibuat.