查询包含mongodb中某些字段的数组元素的数量

时间:2017-03-13 12:11:45

标签: arrays mongodb mongodb-query

我有一组看起来像这样的文件:

{
   my_array : [
      { 
         name : "...", 
         flag : 1 // optional
      },
      ...
   ]
}

如何查询其中一个元素包含标志字段的文档?

这将返回my_array长度恰好为1的文档:

db.col.find({ "my_array" : { $size : 1 } })

这将返回 my_array对象的至少一个包含标记字段的文档:

db.col.find({ "my_array.flag" : { $exists : true } })

这将查找其中flag是大小为1的数组的文档:

db.col.find({ "my_array.flag" : { $size : 1 } })

我想以某种方式组合前两个查询,检查一些内部字段存在,然后查询已过滤数组的大小

3 个答案:

答案 0 :(得分:1)

您可以尝试$redact $filter来查询。

<{>} $filter$ifNull保持匹配元素后跟$size$redact,并将结果与​​1进行比较以保留并删除文档。

db.col.aggregate(
    [{
        $match: {
            "my_array.flag": {
                $exists: true
            }
        }
    }, {
        $redact: {
            $cond: {
                if: {
                    $eq: [{
                        $size: {
                            $filter: {
                                input: "$my_array",
                                as: "array",
                                cond: {
                                    $eq: [{
                                        $ifNull: ["$$array.flag", null]
                                    }, "$$array.flag"]
                                }
                            }
                        }
                    }, 1]
                },
                then: "$$KEEP",
                else: "$$PRUNE"
            }
        }
    }]
)

答案 1 :(得分:0)

在mongodb中使用聚合框架,

管道阶段1:匹配,

          checking for some inner field existence,

         { "my_array.flag" : { $exists : true } }

pipleline阶段2:项目,

         querying for the size of the filtered array,

         {$project:{ "my_array":{$size:"$my_array"}}}

mongoshell Command,

    db.col.aggregate([{
        $match: {
            "my_array.flag": {
                $exists: true
            }
        }
    }, {
        $project: {
            "my_array": {
                $size: "$my_array"
            }
        }
    }])

答案 2 :(得分:0)

根据关于使用聚合的当前答案,以下是使用聚合的工作解决方案:

db.col.aggregate([
{ $match : { "my_array.flag" : { $exists : true } } },
{ $unwind : "$my_array" },
{ $match : { "my_array.flag" : { $exists : true } } },
{ $group : { _id : "$_id", count_flags : { $sum : 1 } } },
{ $match : { "count_flags" : 1 } }
])

以下是解释的步骤:

  1. 仅过滤包含至少一个flag字段的文档(这将使用我的索引来大幅减少我需要处理的文档数量)
  2. 展开my_array数组,以便能够将每个元素作为单独的文档处理
  3. 从不包含flag
  4. 的元素中过滤分离的文档
  5. 再次按_id分组,并计算元素(包含flag字段)
  6. 按新count_flags字段
  7. 进行过滤

    我不太喜欢这个解决方案,在标准mongo find查询中获取基本支持的内容似乎有很多步骤。