Mengingat dokumen ini disimpan di MongoDB
{
_id : ...,
some_key: {
param1 : "val1",
param2 : "val2",
param3 : "val3"
}
}
Objek dengan informasi baru tentang param2
dan param3
dari dunia luar perlu diselamatkan
var new_info = {
param2 : "val2_new",
param3 : "val3_new"
};
Saya ingin menggabungkan / overlay bidang baru di atas keadaan objek yang ada sehingga param1 tidak dihapus
Melakukan ini
db.collection.update( { _id:...} , { $set: { some_key : new_info } }
Akan mengarah ke MongoDB melakukan persis seperti yang diminta, dan menetapkan some_key ke nilai itu. mengganti yang lama.
{
_id : ...,
some_key: {
param2 : "val2_new",
param3 : "val3_new"
}
}
Apa cara agar MongoDB hanya memperbarui bidang baru (tanpa menyatakannya satu per satu secara eksplisit)? untuk mendapatkan ini:
{
_id : ...,
some_key: {
param1 : "val1",
param2 : "val2_new",
param3 : "val3_new"
}
}
Saya menggunakan klien Java, tetapi contoh apa pun akan dihargai
mongodb
mongodb-java
Eran Medan
sumber
sumber
Jawaban:
Jika saya memahami pertanyaan dengan benar, Anda ingin memperbarui dokumen dengan konten dokumen lain, tetapi hanya bidang yang belum ada, dan abaikan bidang yang sudah disetel (bahkan jika ke nilai lain).
Tidak ada cara untuk melakukan itu dalam satu perintah.
Anda harus menanyakan dokumen terlebih dahulu, mencari tahu apa yang Anda inginkan
$set
dan kemudian memperbaruinya (menggunakan nilai-nilai lama sebagai filter yang cocok untuk memastikan Anda tidak mendapatkan pembaruan bersamaan di antaranya).Pembacaan lain dari pertanyaan Anda adalah Anda senang
$set
, tetapi tidak ingin secara eksplisit mengatur semua bidang. Bagaimana Anda mengirimkan data?Anda tahu Anda dapat melakukan hal berikut:
sumber
db.collection.update( { _id:...} , { $set: someObjectWithNewData, { $multi: true } } )
Saya menyelesaikannya dengan fungsi saya sendiri. Jika Anda ingin memperbarui bidang yang ditentukan dalam dokumen, Anda harus mengatasinya dengan jelas.
Contoh:
Jika Anda ingin memperbarui param2 saja, itu salah untuk dilakukan:
Anda harus menggunakan:
Jadi saya menulis fungsi seperti itu:
sumber
db.users.update( { _id: ObjectId("594dbc3186bb5c84442949b1") }, { $set: { resume: { url: "http://i.imgur.com/UFX0yXs.jpg" } } } )
Anda dapat menggunakan notasi titik untuk mengakses dan mengatur bidang di dalam objek, tanpa memengaruhi properti lain dari objek tersebut.
Diberikan objek yang Anda tentukan di atas:
Kami dapat memperbarui secara adil
some_key.param2
dansome_key.param3
:Anda dapat mempelajari sedalam yang Anda inginkan. Ini juga berguna untuk menambahkan properti baru ke objek tanpa mempengaruhi yang sudah ada.
sumber
Solusi terbaik adalah mengekstraksi properti dari objek dan menjadikannya pasangan nilai kunci dot-notasi datar. Anda dapat menggunakan misalnya perpustakaan ini:
https://www.npmjs.com/package/mongo-dot-notation
Memiliki
.flatten
fungsi yang memungkinkan Anda untuk mengubah objek menjadi properti set datar yang kemudian dapat diberikan kepada $ set modifier, tanpa khawatir properti properti objek DB Anda yang ada akan dihapus / ditimpa tanpa perlu.Diambil dari
mongo-dot-notation
dokumen:Dan kemudian itu membentuk pemilih sempurna - itu akan memperbarui HANYA properti yang diberikan. EDIT: Saya suka menjadi arkeolog beberapa kali;)
sumber
Mongo memungkinkan Anda memperbarui dokumen bersarang menggunakan
.
konvensi. Lihatlah: Memperbarui dokumen bersarang di mongodb . Berikut pertanyaan lain dari masa lalu tentang pembaruan gabungan, seperti yang Anda cari saya percaya: pembaruan atom MongoDB melalui dokumen 'gabungan'sumber
Saya berhasil melakukannya dengan cara ini:
Saya memiliki fungsi yang menangani pembaruan profil saya secara dinamis
Catatan: 'profil' khusus untuk implementasi saya, hanya string kunci yang ingin Anda modifikasi.
sumber
Sepertinya Anda dapat mengatur isPartialObject yang dapat mencapai apa yang Anda inginkan.
sumber
Jika Anda memiliki beberapa bidang yang akan diperbarui
sumber
Mulai
Mongo 4.2
,db.collection.update()
dapat menerima pipa agregasi, yang memungkinkan menggunakan operator agregasi seperti$addFields
, yang menampilkan semua bidang yang ada dari dokumen input dan bidang yang baru ditambahkan:Bagian pertama
{}
adalah kueri kecocokan, memfilter dokumen mana yang akan diperbarui (dalam hal ini semua dokumen).Bagian kedua
[{ $addFields: { some_key: new_info } }]
adalah pipa agregasi pembaruan:$addFields
.$addFields
melakukan persis apa yang Anda butuhkan: memperbarui objek sehingga objek baru akan overlay / bergabung dengan yang sudah ada:{ param2: "val2_new", param3: "val3_new" }
akan digabung menjadi yang sudah adasome_key
dengan tetapparam1
tidak tersentuh dan menambah atau mengganti keduanyaparam2
danparam3
.Jangan lupa
{ multi: true }
, jika tidak , hanya dokumen yang cocok pertama yang akan diperbarui.sumber
untuk
Semoga bantuan ini!
sumber
Anda bisa melakukan upert, operasi ini di MongoDB digunakan untuk menyimpan dokumen ke dalam koleksi. Jika dokumen cocok dengan kriteria kueri, maka ia akan melakukan operasi pembaruan jika tidak akan memasukkan dokumen baru ke dalam koleksi.
sesuatu yang mirip seperti di bawah ini
sumber
gunakan $ set lakukan proses ini
sumber
Buat objek pembaruan dengan nama properti termasuk jalur titik yang diperlukan. ("somekey." + dari contoh OP), lalu gunakan yang melakukan pembaruan.
sumber
Ya, cara terbaik adalah mengubah notasi objek menjadi representasi string nilai kunci datar, seperti yang disebutkan dalam komentar ini: https://stackoverflow.com/a/39357531/2529199
Saya ingin menyoroti metode alternatif menggunakan perpustakaan NPM ini: https://www.npmjs.com/package/dot-object yang memungkinkan Anda memanipulasi objek yang berbeda menggunakan notasi titik.
Saya menggunakan pola ini untuk secara terprogram membuat properti objek bersarang saat menerima nilai kunci sebagai variabel fungsi, sebagai berikut:
Pola ini memungkinkan saya menggunakan properti bersarang dan tingkat tunggal secara bergantian, dan menyisipkannya dengan bersih ke dalam Mongo.
Jika Anda perlu bermain-main dengan JS Objects di luar hanya Mongo, terutama di sisi klien tetapi memiliki konsistensi ketika bekerja dengan Mongo, perpustakaan ini memberi Anda lebih banyak pilihan daripada
mongo-dot-notation
modul NPM yang disebutkan sebelumnya .PS Saya awalnya hanya ingin menyebutkan ini sebagai komentar tetapi ternyata S / O perwakilan saya tidak cukup tinggi untuk mengirim komentar. Jadi, tidak berusaha mengomentari komentar SzybkiSasza, hanya ingin menyoroti menyediakan modul alternatif.
sumber
Saya mencoba
findAndModify()
memperbarui bidang tertentu di objek yang sudah ada sebelumnya.https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/
sumber
Anda harus berpikir tentang memperbarui objek secara bergantian dan kemudian hanya menyimpan objek dengan bidang yang diperbarui. Sesuatu seperti dilakukan di bawah ini
sumber
Anda harus menggunakan Dokumen Tertanam (stringfy the path object)
Jadi, dalam JavaScript Anda dapat menggunakan Penyebar Operator (...) untuk memperbarui
sumber