Sebenarnya melakukan apa yang Anda katakan sedang Anda lakukan bukanlah operasi tunggal, tetapi saya akan membahas bagian-bagian yang diperlukan untuk melakukan ini atau menutupi kemungkinan situasi lain.
Apa yang Anda cari sebagian adalah $
. posisional operator. Anda memerlukan bagian dari kueri Anda untuk juga "menemukan" elemen larik yang Anda inginkan.
db.products.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
"$set": {
"recentviews.$.vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
)
Jadi $
singkatan dari posisi yang cocok dalam larik sehingga bagian pembaruan mengetahui item mana dalam larik yang akan diperbarui. Anda dapat mengakses masing-masing bidang dokumen dalam larik atau hanya menentukan seluruh dokumen yang akan diperbarui pada posisi itu.
db.products.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
"$set": {
"recentviews.$": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
)
Jika field sebenarnya tidak berubah dan Anda hanya ingin menyisipkan elemen array baru jika elemen yang sama persis tidak ada, maka Anda dapat menggunakan $addToSet
db.products.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
$addToSet:{
"recentviews": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
)
Namun jika Anda hanya mencari "mendorong" ke array dengan nilai kunci tunggal jika itu tidak ada maka Anda perlu melakukan penanganan manual lagi, dengan terlebih dahulu melihat apakah elemen dalam array ada dan kemudian membuat $push
pernyataan di mana tidak.
Anda mendapatkan bantuan dari metode luwak dalam melakukan ini dengan melacak jumlah dokumen yang terpengaruh oleh pembaruan:
Product.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
"$set": {
"recentviews.$": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
},
function(err,numAffected) {
if (numAffected == 0) {
// Document not updated so you can push onto the array
Product.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095")
},
{
"$push": {
"recentviews": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
},
function(err,numAffected) {
}
);
}
}
);
Satu-satunya peringatan di sini adalah bahwa ada sedikit perubahan implementasi dalam pesan writeConcern dari MongoDB 2.6 ke versi sebelumnya. Tidak yakin sekarang tentang bagaimana API luwak sebenarnya mengimplementasikan kembalinya numAffected
argumen dalam panggilan balik perbedaannya bisa berarti sesuatu.
Di versi sebelumnya, bahkan jika data yang Anda kirim di pembaruan awal sama persis dengan elemen yang ada dan tidak ada perubahan nyata yang diperlukan, maka jumlah yang "dimodifikasi" akan dikembalikan sebagai 1
meskipun tidak ada yang benar-benar diperbarui.
Dari MongoDB 2.6, respons kekhawatiran penulisan berisi dua bagian. Satu bagian menunjukkan dokumen yang dimodifikasi dan yang lainnya menunjukkan kecocokan. Jadi sementara kecocokan akan dikembalikan oleh bagian kueri yang cocok dengan elemen yang ada, jumlah dokumen yang dimodifikasi sebenarnya akan kembali sebagai 0
jika sebenarnya tidak ada perubahan yang diperlukan.
Jadi tergantung pada bagaimana nomor pengembalian sebenarnya diterapkan di luwak, mungkin sebenarnya lebih aman menggunakan $addToSet
operator pada pembaruan dalam untuk memastikan bahwa jika alasan nol dokumen yang terpengaruh bukan hanya karena elemen persisnya sudah ada.