2017-02-09 35 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'] 
}] 

那么结果就是我想要的是这样的:

{ 
    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

使用聚合时可以做什么是一个包含language:label的组合索引。

假设你是返回一个承诺,我将做到以下几点:

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; 

在主叫代码,你将不得不做这样的事情:

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

我相信会做。

+0

不能正常工作... [{_id:null,labels:[[Object],[Object]],count:0}] –

+0

它在第二个ID中缺少双引号。我的回答已被编辑。请立即检查。我只是在这里测试,它的工作。 –

+0

顺便说一句,[{“_id”:null,“labels”:[{“label”:“old”},{“label”:“new”}],“count”:0}],双引号不是你错过的唯一部分... –

0

感谢@Styvane鼓舞人心的,我的最终版本,基于mongoDB 3.4。

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 
        } 
       } 
      ] 
     } 
    } 
])