mongodb聚合查询?

纯前端一枚,之前没有接触后台数据库,现在学习mongodb数据库,遇到这样的一个情景,建立一个博客的数据库,有这样一个包含所有文章信息的集合,数据伪造如下:

{ "id" : 1, "name" : "one", "tags" : [ "a", "c", "e" ] }
{ "id" : 2, "name" : "two", "tags" : [ "e" ] }
{ "id" : 3, "name" : "three", "tags" : [ "d", "e" ] }
{ "id" : 4, "name" : "four", "tags" : [ "g", "c", "e", "h" ] }
{ "id" : 5, "name" : "five", "tags" : [ "a", "c", "d" ] }

tags 表示这篇文章所属的标签类型,现在想要查询出有多少个不同的标签类型,每个标签下有多少条数据,这个该怎么实现?目前想到的是用 aggregate 中的 $unwind 将 tags 进行拆分,然后再用 $group 进行分组统计,但是具体代码该怎么写,或者是有其他更有效的方式,请指教!!!

阅读 2.2k
2 个回答

这是个很经典的统计问题,其实已经不是MongoDB特有的范畴了,对于其他数据库来讲也是通用的。
你想的办法本身是没有问题的,肯定可以通过aggregation的$unwind+$group得到你想要的结果。问题在于随着时间推移,参与统计的博客数量将会越来越多,意味着你的统计语句将越来越慢。问题的关键在于如何限制住每次参与统计的记录数。
从另一个角度讲,博客一般写完就很少有改动了,今天统计昨天的所有博客各属于哪些标签,跟明天再来统计昨天的得到的结果应该是一样的(假设没有修改的前提下)。所以每次都进行统计其实是浪费。
基于以上这些考虑,你其实可以每隔一段时间(比如每天)统计一次每个标签都有多少次出现,把它们存起来,在需要时再把这些已经聚合过一次的数据再次聚合。这种方式称为预聚合。
大概的方向是这样,细节的问题你可以先自己思考一下。

数据提取出来后,这就是纯统计算法问题了,跟是否前后端无关,当然实现起来也是比较简单

const list = [
  {"id": 1, "name": "one", "tags": ["a", "c", "e"]},
  {"id": 2, "name": "two", "tags": ["e"]},
  {"id": 3, "name": "three", "tags": ["d", "e"]},
  {"id": 4, "name": "four", "tags": ["g", "c", "e", "h"]},
  {"id": 5, "name": "five", "tags": ["a", "c", "d"]}
];
const result = {
  length: 0 //不同的标签类型个数
};
list.forEach(item => {
  item.tags.forEach(tag => {
    if (!result[tag]) {
      result[tag] = {
        name: tag,  //标签名
        list: []    //包含含有此标签的id 数组length就是此标签下的条目数
      };
      result.length += 1;
    }
    result[tag].list.push(item.id);
  })
});
console.log(result)
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进