MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

Cara lebih mudah untuk Memperbarui Array dengan MongoDB

Jika Anda "peduli" tentang menambahkan lebih banyak fungsionalitas di sini (sangat disarankan) dan membatasi overhead pembaruan di mana Anda benar-benar tidak perlu mengembalikan dokumen yang dimodifikasi, atau bahkan jika Anda melakukannya, selalu lebih baik menggunakan operator atom dengan array seperti $push dan $addToSet .

"Fungsi tambahan" juga ketika menggunakan array dalam penyimpanan, adalah praktik yang sangat bijaksana untuk menyimpan "panjang" atau "jumlah" item. Ini berguna dalam kueri dan dapat diakses secara efisien dengan "indeks", berbeda dengan metode lain untuk mendapatkan "jumlah" larik atau menggunakan "jumlah/panjang" itu untuk tujuan pemfilteran.

Konstruksi yang lebih baik di sini adalah menggunakan operasi "Bulk" karena pengujian untuk elemen array yang ada tidak cocok dengan konsep "upsert", jadi di mana Anda ingin meningkatkan fungsionalitas, pengujian array lebih baik dalam dua operasi. Tetapi karena operasi "Massal" dapat dikirim ke server dengan "satu permintaan" dan Anda juga mendapatkan "satu tanggapan", maka ini mengurangi biaya overhead yang nyata dalam melakukannya.

var bulk = FollowModel.collection.initializeOrderedBulkOp();

// Try to add where not found in array
bulk.find({ 
    "facebookId": req.user.facebookId,
    "players": { "$ne": req.body.idToFollow }
}).updateOne({
    "$push": { "players": req.body.idToFollow },
    "$inc": { "playerCount": 1 }
});

// Otherwise create the document if not matched
bulk.find({
    "facebookId": req.user.facebookId,
}).upsert().updateOne({
    "$setOnInsert": {
        "players": [req.body.idToFollow]
        "playerCount": 1,
        "fans": [],
        "fanCount": 0
    }
})

bulk.execute(function(err,result) {
    // Handling in here
});

Cara kerjanya adalah bahwa upaya pertama di sana mencoba menemukan dokumen di mana elemen array yang akan ditambahkan belum ada di dalam array. Tidak ada upaya yang dilakukan pada "upsert" di sini karena Anda tidak ingin membuat dokumen baru jika satu-satunya alasan tidak cocok dengan dokumen adalah karena elemen array tidak ada. Tetapi jika cocok, maka anggota baru ditambahkan ke larik dan "jumlah" saat ini "bertambah" 1 melalui $inc , yang menyimpan jumlah atau panjang total.

Pernyataan kedua karena itu akan cocok dengan dokumen saja, dan karena itu menggunakan "upsert" karena jika dokumen tidak ditemukan untuk bidang kunci maka itu akan dibuat. Karena semua operasi ada di dalam $setOnInsert maka tidak akan ada operasi yang dilakukan jika dokumen sudah ada.

Ini semua benar-benar hanya satu permintaan dan respons server, jadi tidak ada "bolak-balik" untuk memasukkan dua operasi pembaruan, dan itu membuat ini efisien.

Menghapus entri array pada dasarnya adalah kebalikannya, kecuali kali ini tidak perlu "membuat" dokumen baru jika tidak ditemukan:

var bulk = FollowModel.collection.initializeOrderedBulkOp();

// Try to remove where found in array
bulk.find({ 
    "facebookId": req.user.facebookId,
    "players": req.body.idToFollow
}).updateOne({
     "$pull": { "players": req.body.idToFollow },
     "$inc": { "playerCount": -1 }
});

bulk.execute(function(err,result) {
    // Handling in here
});

Jadi sekarang Anda hanya perlu menguji di mana elemen array ada dan di mana kemudian $pull elemen yang cocok dari konten larik, bersamaan dengan "mengurangi" "hitungan" sebanyak 1 untuk mencerminkan penghapusan.

Sekarang Anda "bisa" menggunakan $addToSet alih-alih di sini karena hanya akan melihat konten array dan jika anggota tidak ditemukan maka akan ditambahkan, dan dengan alasan yang sama tidak perlu menguji elemen array yang ada saat menggunakan $pull karena itu tidak akan melakukan apa-apa jika elemennya tidak ada. Selanjutnya $addToSet dalam konteks itu dapat digunakan secara langsung dalam "upsert", selama Anda tidak "bersilang" karena tidak diizinkan untuk mencoba dan menggunakan beberapa operator pembaruan di jalur yang sama dengan MongoDB:

FollowModel.update(
    { "facebookId": req.user.facebookId },
    {
        "$setOnInsert": {
            "fans": []
        },
        "$addToSet": { "players": req.body.idToFollow }
    },
    { "upsert": true },
    function(err,numAffected) {
        // handling in here
    }
);

Tapi ini akan menjadi "salah":

FollowModel.update(
    { "facebookId": req.user.facebookId },
    {
        "$setOnInsert": {
            "players": [],              // <-- This is a conflict
            "fans": []
        },
        "$addToSet": { "players": req.body.idToFollow }
    },
    { "upsert": true },
    function(err,numAffected) {
        // handling in here
    }
);

Namun, dengan melakukan itu, Anda kehilangan fungsionalitas "hitungan" karena operasi tersebut hanya selesai tanpa memperhatikan apa yang sebenarnya ada atau jika ada yang "ditambahkan" atau "dihapus".

Menyimpan "penghitung" adalah hal yang sangat bagus, dan bahkan jika Anda tidak langsung menggunakannya saat ini, maka pada tahap tertentu dalam siklus hidup aplikasi Anda, Anda mungkin akan menginginkannya. Jadi sangat masuk akal untuk memahami logika yang terlibat dan menerapkannya sekarang. Harga kecil yang harus dibayar sekarang untuk banyak manfaat nanti.

Sidenote cepat di sini karena saya biasanya merekomendasikan operasi "Massal" jika memungkinkan. Saat menggunakan ini melalui .collection accessor di luwak, maka Anda perlu menyadari bahwa ini adalah metode driver asli dan karenanya berperilaku berbeda dari metode "luwak".

Khususnya, semua metode "luwak" memiliki "pemeriksaan" bawaan untuk melihat bahwa koneksi ke database sedang aktif. Dimana tidak, operasi secara efektif "antri" sampai sambungan dibuat. Menggunakan metode asli "pemeriksaan" ini tidak lagi ada. Oleh karena itu, Anda perlu memastikan bahwa koneksi sudah ada dari metode "luwak" yang telah mengeksekusi "pertama", atau secara bergantian membungkus Anda seluruh logika aplikasi dalam konstruksi yang "menunggu" koneksi dibuat:

mongoose.connection.on("open",function(err) {
    // All app logic or start in here
});

Dengan begitu Anda yakin bahwa ada koneksi yang ada dan objek yang benar dapat dikembalikan dan digunakan oleh metode. Tapi tidak ada koneksi, dan operasi "Massal" akan gagal.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Buat Indeks Teks Multi-Bahasa di MongoDB

  2. OpenShift Mengakses Pod Mongodb dari Pod lain

  3. Apa yang lebih cepat:`find().limit(1)` atau `findOne()` di MongoDB/Mongoose?

  4. kafka connector debezium mongodb CDC update/$set message tanpa filter(_id value)

  5. mongoDB Ganti nama bidang yang disematkan