Jika saya pada dasarnya mendapatkan inti Anda, pada dasarnya Anda ingin
- Tarik item yang tidak diperlukan dari larik referensi Anda
- Setel nilai bidang referensi utama Anda ke elemen pertama dari larik yang diubah
Dan selesaikan semuanya dalam satu pembaruan tanpa memindahkan dokumen melalui kabel.
Tapi sayangnya ini tidak bisa dilakukan. Masalah utama dengan ini adalah bahwa tidak ada cara untuk merujuk ke nilai bidang lain dalam dokumen yang sedang diperbarui. Meski begitu, untuk melakukan ini tanpa mengulangi, Anda juga perlu mengakses yang diubah array untuk mendapatkan elemen pertama yang baru.
Mungkin satu pendekatan adalah memikirkan kembali skema Anda untuk mencapai apa yang Anda inginkan. Opsi saya di sini akan sedikit memperluas dokumen referensi Anda dan menghilangkan kebutuhan akan bidang referensi utama.
Tampaknya asumsi yang ingin Anda jalani pada pembaruan adalah bahwa jika referensi yang dihapus adalah referensi utama maka Anda dapat mengatur referensi utama baru ke elemen pertama dalam array. Dengan mengingat hal itu, pertimbangkan struktur berikut:
refs: [ { oid: "object1" }, { oid: "object2" }, { oid: "object5", main: true } ]
Dengan mengubahnya menjadi dokumen dengan oid
properti yang akan disetel ke ObjectId itu memberikan opsi untuk memiliki properti tambahan pada dokumen yang menentukan mana yang default. Ini dapat dengan mudah ditanyakan untuk menentukan Id mana yang menjadi referensi utama.
Sekarang pertimbangkan juga apa yang akan terjadi jika dokumen yang cocok dengan "object5" di bidang oid ditarik dari larik:
refs: [ { oid: "object1" }, { oid: "object2" } ]
Jadi ketika Anda menanyakan yang mana main-reference
sesuai logika sebelumnya Anda menerima dokumen pertama dalam array. Sekarang tentu saja, untuk persyaratan aplikasi Anda, jika Anda ingin menetapkan main-reference
yang berbeda Anda tinggal mengubah dokumen
refs: [ { oid: "object1" }, { oid: "object2", main: true } ]
Dan sekarang logikanya tetap memilih elemen array yang memiliki properti utama sebagai true akan terjadi dalam preferensi, dan seperti yang ditunjukkan di atas bahwa jika properti itu tidak ada pada dokumen elemen apa pun maka kembali ke elemen pertama.
Dengan semua yang dicerna, operasi Anda untuk menarik semua referensi ke objek dari array itu di semua dokumen menjadi sangat sederhana, seperti yang dilakukan di shell ( format yang sama pada dasarnya berlaku untuk driver apa pun ):
db.books.update(
{ "refs.oid": "object5" },
{ $pull: { refs: {oid: "object5"} } }, false, true )
Dua argumen tambahan untuk operasi kueri dan pembaruan adalah upsert
dan multi
masing-masing. Dalam hal ini, upsert
tidak masuk akal karena kita hanya ingin memodifikasi dokumen yang ada, dan multi
berarti kami ingin memperbarui semua yang cocok. Standarnya adalah mengubah hanya dokumen pertama.
Secara alami saya mempersingkat semua notasi tetapi tentu saja nilainya dapat berupa ObjectId aktual sesuai maksud Anda. Tampaknya juga masuk akal untuk menganggap bahwa penggunaan utama Anda atas main-reference
adalah setelah Anda mengambil dokumen. Mendefinisikan kueri yang mengembalikan main-reference
dengan mengikuti logika yang digariskan seharusnya bisa, tapi ternyata saya sudah banyak mengetik di sini dan perlu istirahat untuk makan malam :)
Saya pikir ini merupakan kasus yang berharga untuk memikirkan kembali skema Anda untuk menghindari iterasi yang berlebihan untuk apa yang ingin Anda capai.