MongoDB子文档的快速计数-可能是索引

MongoDB子文档的快速计数-可能是索引,mongodb,b-tree,Mongodb,B Tree,我在MongoDB Atlas集群上使用MongoDB 4.0(3个副本-1个碎片) 假设我有一个包含多个文档的集合 这些文档中的每一个都包含一个子文档数组,这些子文档表示特定年份的城市以及其他信息。示例文档如下所示(为了简化示例,我删除了不必要的信息): 我有一个年和月的复合指数。计算姓名和年份组合出现次数的最快方法是什么 我已经尝试了以下聚合: [{$unwind: { path: '$cities' }}, {$group: { _id: { name: 'cities.n

我在MongoDB Atlas集群上使用MongoDB 4.0(3个副本-1个碎片)

假设我有一个包含多个文档的集合

这些文档中的每一个都包含一个子文档数组,这些子文档表示特定年份的城市以及其他信息。示例文档如下所示(为了简化示例,我删除了不必要的信息):

我有一个年和月的复合指数。计算姓名和年份组合出现次数的最快方法是什么

我已经尝试了以下聚合:

[{$unwind: {
  path: '$cities'
}}, {$group: {
  _id: {
    name: 'cities.name',
    year: '$cities.year'
  },
  count: {
    $sum: 1
  }
}}, {$project: {
  count: 1,
  name: '$_id.name',
  year: '$_id.year',
  _id: 0
}}]
我尝试的另一种方法是以下形式的map reduce——map reduce的性能稍好一些,所需时间减少了30%

地图功能:

function m() {
    for (var i in this.cities) {
        emit({
                name: this.cities[i].name,
                year: this.cities[i].year
            },
            1);
    }
}
reduce函数(也尝试用长度替换sum,但令人惊讶的是sum更快):

mongoshell中的函数调用:

db.test.mapReduce(m,r,{out:"mr_test"})
现在我在问自己——有可能访问索引吗?据我所知,这是一个B+树,它保存指向磁盘上相关文档的指针,因此从技术角度来看,我认为有可能遍历索引树的所有叶子,只计算指针?有人知道这是否可能吗


有人知道另一种高性能解决方法吗?(由于软件的其他依赖性,不可能更改设计,我们在一个非常大的数据集上运行此功能)。有没有人可能有通过碎片解决这类任务的经验?

在这种情况下,索引不会有很大帮助

MongoDB索引设计用于识别符合给定标准的文档

如果您在
{cities.name:1,cities.year:1}

本文件:

{_id:123,
 cities:[
  {name:"vienna",
   year:1985
  },
  {name:"berlin",
   year:2001
  }
  {name:"vienna",
   year:1985
  }
]}
vienna|1985
berlin|2001
在b-树中有两个参考本文档的条目:

{_id:123,
 cities:[
  {name:"vienna",
   year:1985
  },
  {name:"berlin",
   year:2001
  }
  {name:"vienna",
   year:1985
  }
]}
vienna|1985
berlin|2001
即使可以计算索引中特定键的发生率,也不一定对应

MongoDB不提供检查索引中原始项的方法,并且它明确拒绝在包含数组的字段上使用索引进行计数

MongoDB count命令和helper用于所有count文档,而不是其中的元素。正如您所注意到的,您可以展开数组并对聚合管道中的项进行计数,但此时您已经将所有文档加载到内存中,因此使用索引为时已晚