0

这是集合结构

[{
   "_id"              : "....",
   "name"             : "aaaa",
   "level_max_leaves" : [
                           {
                              level      : "ObjectIdString 1",
                              max_leaves : 4,
                           }
                        ]
},
{
   "_id"              : "....",
   "name"             : "bbbb",
   "level_max_leaves" : [
                           {
                              level      : "ObjectIdString 2",
                              max_leaves : 2,
                           }
                        ]
}]

level_max_leaves.level当过滤器与给定的输入值匹配时,我需要找到过滤器的子文档值。

这就是我尝试的方式,

For example,

var empLevelId = 'ObjectIdString 1' ;

MyModel.aggregate(
    {$unwind: "$level_max_leaves"},
    {$match: {"$level_max_leaves.level": empLevelId } },
    {$group: { "_id": "$level_max_leaves.level", 
               "total": { "$sum": "$level_max_leaves.max_leaves" }}},
    function (err, res) {
        console.log(res);
});

但是这里的$match过滤器不起作用。我找不到确切的结果ObjectIdString 1

name如果我用字段过滤,它工作正常。像这样,

{$match: {"$name": "aaaa" } },

但在子文档级别它的回报0

{$match: {"$level_max_leaves.level": "ObjectIdString 1"} },

我的预期结果是,

{
   "_id"              : "ObjectIdString 1",
   "total"            : 4,
}
4

1 回答 1

0

你打错了$match。带有$前缀的字段要么用于已实现的运算符,要么用于对字段内容的“变量”引用。因此,您只需输入字段名称:

MyModel.aggregate(
    [
        { "$match": { "level_max_leaves.level": "ObjectIdString 1" } },
        { "$unwind": "$level_max_leaves" },
        { "$match": { "level_max_leaves.level": "ObjectIdString 1" } },
        { "$group": { 
            "_id": "$level_max_leaves.level", 
           "total": { "$sum": "$level_max_leaves.max_leaves" }
        }}
    ],
    function (err, res) {
        console.log(res); 
    }
);

您提供的样本中的哪个产生:

{ "_id" : "ObjectIdString 1", "total" : 4 }

$match首先进入您的管道也是一个好习惯。这实际上是唯一一次可以使用索引。但不仅如此,因为没有初始$match语句,您的聚合管道将对集合中的每个文档执行$unwind操作,无论它是否满足条件。

所以通常你想要在这里做的是

  1. 匹配数组中包含所需元素的文档
  2. 展开匹配文档的数组
  3. 匹配所需的数组内容,不包括所有其他内容
于 2014-08-22T02:29:37.793 回答