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

Cara menggabungkan bidang array dalam dokumen dalam agregasi Mongo

TLDR;

Rilis modern harus menggunakan $reduce dengan $setUnion setelah $group initial awal seperti yang ditunjukkan:

db.collection.aggregate([
  { "$group": {
    "_id": { "Host": "$Host", "ArtId": "$ArtId" },
    "count": { "$sum": 1 },
    "tags": { "$addToSet": "$tags" }
  }},
  { "$addFields": {
    "tags": {
      "$reduce": {
        "input": "$tags",
        "initialValue": [],
        "in": { "$setUnion": [ "$$value", "$$this" ] }
      }
    }
  }}
])

Anda benar dalam menemukan $addToSet operator, tetapi ketika bekerja dengan konten dalam array, Anda biasanya perlu memproses dengan $unwind pertama. Ini "mendenormalisasi" entri array dan pada dasarnya membuat "salinan" dokumen induk dengan setiap entri array sebagai nilai tunggal di bidang. Itulah yang Anda butuhkan untuk menghindari perilaku yang Anda lihat tanpa menggunakannya.

"Hitungan" Anda menimbulkan masalah yang menarik, tetapi mudah diselesaikan melalui penggunaan "penguraian ganda" setelah $group awal operasi:

db.collection.aggregate([
    // Group on the compound key and get the occurrences first
    { "$group": {
        "_id": { "Host": "$Host", "ArtId": "$ArtId" },
        "tcount": { "$sum": 1 },
        "ttags": { "$push": "$tags" }
    }},

    // Unwind twice because "ttags" is now an array of arrays
    { "$unwind": "$ttags" },
    { "$unwind": "$ttags" },

    // Now use $addToSet to get the distinct values        
    { "$group": {
        "_id": "$_id",
        "tcount": { "$first": "$tcount" },
        "tags": { "$addToSet": "$ttags" }
    }},

    // Optionally $project to get the fields out of the _id key
    { "$project": {
        "_id": 0,
        "Host": "$_id.Host",
        "ArtId": "$_id.ArtId",
        "count": "$tcount",
        "tags": "$ttags"
    }}
])

Bagian terakhir dengan $project ada juga karena saya menggunakan nama "sementara" untuk masing-masing bidang di tahap lain dari pipa agregasi. Ini karena ada pengoptimalan di $project bahwa "menyalin" bidang dari tahap yang ada dalam urutan yang sudah muncul "sebelum" bidang "baru" ditambahkan ke dokumen.

Jika tidak, hasilnya akan terlihat seperti:

{  "count":2 , "tags":[ "tag1", "tag2", "tag3" ], "Host": "abc.com", "ArtId": "123" }

Di mana bidangnya tidak dalam urutan yang sama seperti yang Anda kira. Benar-benar sepele, tetapi penting bagi sebagian orang, jadi perlu dijelaskan alasannya, dan cara menanganinya.

Jadi $unwind melakukan pekerjaan untuk menjaga item terpisah dan tidak dalam array, dan melakukan $group pertama memungkinkan Anda untuk mendapatkan "hitungan" kemunculan kunci "pengelompokan".

$first operator kemudian menggunakan "menyimpan" nilai "hitungan" itu, karena baru saja "digandakan" untuk setiap nilai yang ada dalam larik "tag". Itu semua nilainya sama saja jadi tidak masalah. Pilih satu saja.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. pengurutan MongoDB()

  2. Bahaya Membangun Indeks di MongoDB

  3. Filter dengan driver regex MongoDB C#

  4. Kegagalan Database Transparan untuk Aplikasi Anda

  5. Kueri di Bidang Hash Mongoid