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

Jumlah subdokumen dalam bahasa luwak

Menggunakan aggregate() fungsi, Anda dapat menjalankan pipa berikut yang menggunakan $sum operator untuk mendapatkan hasil yang diinginkan:

const results = await Cart.aggregate([
    { "$addFields": {
        "totalPrice": {
            "$sum": "$products.subTotal"
        }
    } },
]);

console.log(JSON.stringify(results, null, 4));

dan operasi pembaruan yang sesuai mengikuti:

db.carts.updateMany(
   { },
   [
        { "$set": {
            "totalPrice": {
                "$sum": "$products.subTotal"
            }
        } },
    ]
)

Atau jika menggunakan MongoDB 3.2 dan versi sebelumnya, di mana $sum tersedia di $group stage saja, Anda dapat melakukannya

const pipeline = [
    { "$unwind": "$products" },
    {
        "$group": {
            "_id": "$_id",
            "products": { "$push": "$products" },
            "userPurchased": { "$first": "$userPurchased" },
            "totalPrice": { "$sum": "$products.subTotal" }
        }
    }
]

Cart.aggregate(pipeline)
    .exec(function(err, results){
        if (err) throw err;
        console.log(JSON.stringify(results, null, 4));
    })

Pada pipeline di atas, langkah pertama adalah $unwind operator

{ "$unwind": "$products" }

yang sangat berguna ketika data disimpan sebagai array. Ketika operator pelepasan diterapkan pada bidang data daftar, itu akan menghasilkan catatan baru untuk setiap elemen dari bidang data daftar tempat pelepasan diterapkan. Ini pada dasarnya meratakan data.

Ini adalah operasi yang diperlukan untuk tahap pipeline berikutnya, $group langkah di mana Anda mengelompokkan dokumen yang diratakan dengan _id bidang, sehingga secara efektif mengelompokkan kembali dokumen yang didenormalisasi kembali ke skema aslinya.

$group operator pipa mirip dengan GROUP BY SQL ayat. Dalam SQL, Anda tidak dapat menggunakan GROUP BY kecuali Anda menggunakan salah satu fungsi agregasi. Dengan cara yang sama, Anda juga harus menggunakan fungsi agregasi di MongoDB (disebut akumulator). Anda dapat membaca lebih lanjut tentang akumulator di sini .

Dalam $group operasi, logika untuk menghitung totalPrice dan mengembalikan kolom asli adalah melalui akumulator . Anda mendapatkantotalHarga dengan menjumlahkan masing-masing subTotal nilai per grup dengan $sum sebagai:

"totalPrice": { "$sum": "$products.subTotal }

Ekspresi lainnya

"userPurchased": { "$first": "$userPurchased" },

akan mengembalikan userPurchased nilai dari dokumen pertama untuk setiap grup menggunakan $first . Jadi secara efektif membangun kembali skema dokumen asli sebelum $unwind

Satu hal yang perlu diperhatikan di sini adalah ketika menjalankan pipeline, MongoDB menyalurkan operator ke satu sama lain. "Pipa" di sini mengambil arti Linux:output dari operator menjadi input dari operator berikut. Hasil dari setiap operator adalah kumpulan dokumen baru. Jadi Mongo mengeksekusi pipa di atas sebagai berikut:

collection | $unwind | $group => result

Sebagai catatan tambahan, untuk membantu memahami pipeline atau men-debug-nya jika Anda mendapatkan hasil yang tidak terduga, jalankan agregasi hanya dengan operator pipeline pertama. Misalnya, jalankan agregasi di mongo shell sebagai:

db.cart.aggregate([
    { "$unwind": "$products" }
])

Periksa hasilnya untuk melihat apakah produk array didekonstruksi dengan benar. Jika itu memberikan hasil yang diharapkan, tambahkan berikutnya:

db.cart.aggregate([
    { "$unwind": "$products" },
    {
        "$group": {
            "_id": "$_id",
            "products": { "$push": "$products" },
            "userPurchased": { "$first": "$userPurchased" },
            "totalPrice": { "$sum": "$products.subTotal" }
        }
    }
])

Ulangi langkah-langkah tersebut sampai Anda mencapai langkah pipa terakhir.

Jika Anda ingin memperbarui bidang, Anda dapat menambahkan $out tahap pipa sebagai langkah terakhir. Ini akan menulis dokumen yang dihasilkan dari pipa agregasi ke koleksi yang sama, sehingga secara teknis memperbarui koleksi.

var pipeline = [
    { "$unwind": "$products" },
    {
        "$group": {
            "_id": "$_id",
            "products": { "$push": "$products" },
            "userPurchased": { "$first": "$userPurchased" },
            "totalPrice": { "$sum": "$products.subTotal" }
        }
    },
    { "$out": "cart" } // write the results to the same underlying mongo collection
]

PERBARUI

Untuk melakukan pembaruan dan kueri, Anda dapat mengeluarkan find() panggil panggilan balik agregat untuk mendapatkan json yang diperbarui yaitu

Cart.aggregate(pipeline)
    .exec(function(err, results){
        if (err) throw err;
        Cart.find().exec(function(err, docs){
            if (err) return handleError(err);
            console.log(JSON.stringify(docs, null, 4));
        })
    })
    

Menggunakan Promises, Anda dapat melakukan ini sebagai alternatif

Cart.aggregate(pipeline).exec().then(function(res)
    return Cart.find().exec();
).then(function(docs){  
    console.log(JSON.stringify(docs, null, 4));
});


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Bagaimana cara membuat bidang Tanggal dengan nilai default sebagai stempel waktu saat ini di MongoDb?

  2. PyMongo vs MongoEngine untuk Django

  3. Apakah normal memiliki banyak koneksi antara node dan mongo saat menggunakan luwak?

  4. Membuat indeks parsial saat bidang bukan nol

  5. Virtual Mongoose di Agregat MongoDB