MongoDb - $match 过滤器在子文档中不起作用

Posted

技术标签:

【中文标题】MongoDb - $match 过滤器在子文档中不起作用【英文标题】:MongoDb - $match filter not working in subdocument 【发布时间】:2014-10-14 21:06:25 【问题描述】:

这是集合结构

[
   "_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,

【问题讨论】:

您提供的值与您指定要匹配的元素上的任何内容都不匹配。通过清楚地说明您要做什么,您实际上可能会得到您想要的。最好的方法是展示预期的结果。 我认为你应该放松一下:"$level_max_leaves" @LalitAgarwal:是的。错字。现在更正它。 @NeilLunn:您已经从上一个问题中知道您计算了所有levelsmax_leaves 的总和。例如,[_id:1, max:5, _id:2, max:7, _id:3, max:6]。如果我在该查询中通过_id: 3。在同样的情况下,现在我需要让叶子特别 level 不是所有人。知道了?结果将是_id: 3, total: 6 为此我添加$match ... 过滤器选项。但我不会被期待。 @NeilLunn:我也更新了我的问题。 【参考方案1】:

您输入了错误的$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 操作,无论它是否满足条件。

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

    匹配数组中包含所需元素的文档 展开匹配文档的数组 匹配所需的数组内容,排除所有其他内容

【讨论】:

感谢您的回复 :)。我删除了 $match 条件中的 $ 前缀。无论哪种方式,它都不会返回任何内容。 @Ranjith 为了明确这一点,人们每天都这样做,所以这不是一个被发现的错误,但你在这里做错了。 empLevelId 是一个变量。在发出查询之前,尝试记录内容以查看其中包含的内容。然后检查您是否确实有一个与您提供的值相匹配的文档。 实际上level_max_leaves.levellevel 集合的ObjectId 父级引用的子文档。所以在动态中empLevelIdLevelObjectId 之一。在问题中提出的上述集合中,它包含一个或多个document 持有不同的level id 和max_leaves。现在我希望根据我的empLevelId 计算所有max_leaves,它被称为LevelIdempLevelId 没有问题。它正确地持有Level id。 @Ranjith 这里有一些你不清楚的地方。我已经编辑了查询以显示应该发生的事情以及在针对您的数据运行时得到的结果,如图所示。

以上是关于MongoDb - $match 过滤器在子文档中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

mongodb aggregate

如何根据 MongoDB 中的列表计数过滤文档? [复制]

如何根据 MongoDB 中的列表计数过滤文档? [复制]

MongoDB 在子文档中查找

如何在任意深度查找 MongoDB 字段名称

在子文档 MongoDB 中检索数组