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

Jumlah Agregat MongoDB Setiap Kunci pada Subdokumen

Seperti yang dinyatakan, pemrosesan dokumen seperti ini tidak mungkin dilakukan dengan kerangka kerja agregasi kecuali Anda benar-benar akan menyediakan semua kunci, seperti:

db.events.aggregate([
   { "$group": {
       "_id": "$app_id",
       "event_count": { "$sum": "$event_count" },
       "0": { "$sum": "$event_count_per_type.0" },
       "10": { "$sum": "$event_count_per_type.10" }
       "20": { "$sum": "$event_count_per_type.20" }
       "30": { "$sum": "$event_count_per_type.30" }
   }}
])

Tetapi Anda tentu saja harus secara eksplisit menentukan setiap kunci yang ingin Anda kerjakan. Ini berlaku untuk kerangka kerja agregasi dan operasi kueri umum di MongoDB, karena untuk mengakses elemen yang dicatat dalam formulir "sub-dokumen" ini, Anda perlu menentukan "jalur yang tepat" ke elemen untuk melakukan apa pun dengannya.

Kerangka agregasi dan kueri umum tidak memiliki konsep "traversal", yang berarti mereka tidak dapat memproses "setiap kunci" dokumen. Itu membutuhkan konstruksi bahasa untuk melakukan yang tidak disediakan di antarmuka ini.

Namun secara umum, menggunakan "nama kunci" sebagai titik data di mana namanya sebenarnya mewakili "nilai" adalah sedikit "anti-pola". Cara yang lebih baik untuk memodelkan ini adalah dengan menggunakan array dan mewakili "tipe" Anda sebagai nilai dengan sendirinya:

{
    "app_id": "DHJFK67JDSJjdasj909",
    "date: ISODate("2014-08-07T00:00:00.000Z"),
    "event_count": 32423,
    "events": [
        { "type": 0,  "value": 322  },
        { "type": 10, "value": 4234 },
        { "type": 20, "value": 653  },
        { "type": 30, "value": 7562 }
    ]
}

Juga mencatat bahwa "tanggal" sekarang menjadi objek tanggal yang tepat daripada string, yang juga merupakan praktik yang baik untuk dilakukan. Jenis data ini mudah diproses dengan kerangka kerja agregasi:

db.events.aggregate([
    { "$unwind": "$events" },
    { "$group": {
        "_id": { 
            "app_id": "$app_id",
            "type": "$events.type"
        },
        "event_count": { "$sum": "$event_count" },
        "value": { "$sum": "$value" }
    }},
    { "$group": {
        "_id": "$_id.app_id",
        "event_count": { "$sum": "$event_count" },
        "events": { "$push": { "type": "$_id.type", "value": "$value" } }
    }}
]) 

Itu menunjukkan pengelompokan dua tahap yang pertama-tama mendapatkan total per "tipe" tanpa menentukan setiap "kunci" karena Anda tidak lagi harus melakukannya, lalu kembali sebagai dokumen tunggal per "app_id" dengan hasil dalam array seperti aslinya disimpan. Formulir data ini umumnya jauh lebih fleksibel untuk melihat "jenis" tertentu atau bahkan "nilai" dalam rentang tertentu.

Di mana Anda tidak dapat mengubah struktur maka satu-satunya pilihan Anda adalah mapReduce. Ini memungkinkan Anda untuk "mengkode" traversal kunci, tetapi karena ini memerlukan interpretasi dan eksekusi JavaScript, ini tidak secepat kerangka kerja agregasi:

db.events.mapReduce(
    function() {
        emit(
            this.app_id,
            {
                "event_count": this.event_count,
                "event_count_per_type": this.event_count_per_type
            }
        );
    },
    function(key,values) {

        var reduced = { "event_count": 0, "event_count_per_type": {} };

        values.forEach(function(value) {
            for ( var k in value.event_count_per_type ) {
                if ( !redcuced.event_count_per_type.hasOwnProperty(k) )
                    reduced.event_count_per_type[k] = 0;
                reduced.event_count_per_type += value.event_count_per_type;
            }
            reduced.event_count += value.event_count;
        })
    },
    {
        "out": { "inline": 1 }
    }
)

Itu pada dasarnya akan melintasi dan menggabungkan "kunci" dan menjumlahkan nilai untuk setiap kunci yang ditemukan.

Jadi pilihan Anda adalah:

  1. Ubah struktur dan kerjakan dengan kueri dan agregasi standar.
  2. Tetap menggunakan struktur dan memerlukan pemrosesan JavaScript dan mapReduce.

Itu tergantung pada kebutuhan Anda yang sebenarnya, tetapi dalam banyak kasus, restrukturisasi menghasilkan manfaat.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Memahami dan Mengelola Ruang Disk di Server MongoDB Anda

  2. Luwak menghapus (menarik) dokumen dalam array, tidak berfungsi dengan ObjectID

  3. Agregasi Mongo :$group dan $project array ke objek untuk penghitungan

  4. MongoDB tidak dapat menemukan direktori data setelah memutakhirkan ke Mac OS 10.15 (Catalina)

  5. Ubah string menjadi angka dalam proyeksi MongoDB