2017-02-09 7 views
3

私はこのようなデータモデルを定義した:mongoDBに関する集約パズル?

import mongoose from 'mongoose'; 

const schema = mongoose.Schema({ 
    title: {type: String, required: true}, 
    content: {type: String, required: true}, 
    language: {type: String, required: true}, 
    label: [{type: String, required: false}], 
    createTime: {type: Date, default: Date.now}, 
    updateTime: {type: Date, default: Date.now} 
}); 

const Snippet = mongoose.model('Snippet', schema, 'snippet'); 

export default Snippet; 

私が欲しいのは、私が使用している場合ということです:

Snippet.aggregate({...}) 

、データがある場合:

[{ 
    title: 'a', 
    content: 'b', 
    language: 'javascript' 
},{ 
    title: 'a', 
    content: 'b', 
    language: 'javascript', 
    label: ['new', 'old'] 
}, 
{ 
    title: 'a', 
    content: 'b', 
    language: 'javascript', 
    label: ['old'] 
}] 

、結果はどのようなI欲しかったのは次のようなものです:

{ 
    languageCount : [ 
    { 
    language : 'javascript', 
    count : 3 
    }], 
    labelCount : [ 
    { 
    label : 'new', 
    count : 1 
    }, 
    { 
    label : 'old', 
    count : 2 
    }] 
} 

「...」の部分をどうやって仕上げるか分かりません。

それについて、または他の方法で考えている人は、誰でもそれを回避できます。ありがとうございます。

+0

あなたの 'mongod'は何ですか? – styvane

+0

私のmongodバージョンは3.2.1です。最新バージョンに基づいていくつかの機能を使用することができます、私はそれで大丈夫です。 –

答えて

2

mongodバージョン< = 3.2の場合、次のパイプラインでこれを行うことができます。

[ 
    { 
     "$unwind":"$label" 
    }, 
    { 
     "$group":{ 
     "_id":{ 
      "lang":"$language", 
      "label":"$label" 
     }, 
     "count_label_per_lang":{ 
      "$sum":1 
     } 
     } 
    }, 
    { 
     "$group":{ 
     "_id":"$_id.lang", 
     "labels":{ 
      "$push":{ 
       "label":"$_id.label", 
       "count":"$count_label_per_lang" 
      } 
     }, 
     "count":{ 
      "$sum":"$count_label_per_lang" 
     } 
     } 
    } 
] 
0

集計を使用するときにできることは、言語:ラベルを含む合成インデックスです。私はそれがどうなると信じて

responsePromise.then((data,error) => { 
    response.json({content:data}) 
}); 

:あなたのような何かをしなければならない、呼び出し元のコードに

const projection = { _id: 1, labels : 1, count:1, languageCount:1 } 
    const responsePromise = Snippet.aggregate([ 
     { 
     $unwind:"$label" 
     }, 
     { 
     $group:{ 
      _id: {language: "$language", label : "$label"}, 
      languageCount:{$sum:1} 
     } 
     }, 
     { 
     $group:{ 
      _id:"$_id.language", 
      labels:{ 
       $push:{ 
       label:"$_id.label", 
       count:"$languageCount" 
       } 
      }, 
     count:{$sum:"$languageCount"} 
     } 
    }, 
    { $project : projection }]); 

    return responsePromise; 

:あなたが約束を戻ってきている、私は次のことを行うだろうと仮定

+0

[{_id:null、ラベル:[[オ​​ブジェクト]、[オブジェクト]]、カウント:0}] –

+0

2番目のIDに二重引用符がありませんでした。私の答えは編集されました。今すぐ確認してください。私はちょうどここでテストし、それは働いた。 –

+0

途中で{{"_id":null、 "labels":[{"label": "old"}、{"label": "new"}、 "count":0}]二重引用符私が逃した唯一の部分ではありません... –

0

mongoDB 3.4をベースにした最終アンサー、@Styvaneの感動のおかげで。

db.getCollection('snippet').aggregate([ 
    { 
     "$facet": { 
      "languageCount": [ 
       { 
        "$sortByCount": "$language" 
       }, 
       { 
        "$addFields": { 
         "language": "$_id" 
        } 
       }, 
       { 
        "$project": { 
         "_id": 0 
        } 
       } 
      ], 
      "labelCount": [ 
       { 
        "$unwind": "$label" 
       }, 
       { 
        "$sortByCount": "$label" 
       }, 
       { 
        "$addFields": { 
         "label": "$_id" 
        } 
       }, 
       { 
        "$project": { 
         "_id": 0 
        } 
       } 
      ] 
     } 
    } 
])