MongoDB:匹配数组元素的计数

时间:2015-04-15 10:45:48

标签: arrays mongodb

我有一个名为" Lines"具有以下结构(基本上,我有很多包含多个数组的文档,我需要用条件来计算它们的元素。)

    {
        "_id" : "201503110040020021",
        "Line" : "1", // several documents may have this Line value
        "LineStart" : ISODate("2015-03-11T06:49:35.000Z"),
        "SSCEXPEND" : [ 
            {
                "Secuence" : 10,
                "Title" : 1,
            }, 
            {
                "Secuence" : 183,
                "Title" : 613,
            }, 
            ...
        ],
        "SSCCANCELATIONS" : [ 
            {
                "Secuence" : 34,
                "Title" : 113,
            }, 
            {
                "Secuence" : 96,
                "Title" : 2,
            }, 
            ... 
        ],
        "SSCVALIDATIONS" : [ 
            {
                "Secuence" : 12,
                "Result" : 1
            }, 
            {
                "Secuence" : 15,
                "Result" : 1,
            },
            {
                "Secuence" : 18,
                "Result" : 20,
            },
            ...
        ]
    },
    ...

我需要的是计算这些数组中有多少元素符合某些条件,例如, 我想数数 SSCCANCELATIONS中的每个元素, 但我只想用SSCEXPEND

计算Title = 1, and SSCVALIDATIONS elements with Result < 10个元素

我可以使用

获取每个数组的元素总数
db.Lines.aggregate( { $project: { Line : 1, Validations: { $size: "$SSCVALIDATIONS" }, ... } } ) 

但我需要坚持条件,得到类似的东西:

    {
        "_id" : "201503110040020021",
        "Line" : "1",
        "LineStart" : ISODate("2015-03-11T06:49:35.000Z"),
        "SSCEXPEND" : 15,
        "SSCCANCELATIONS" : 10,
        "SSCVALIDATIONS" : 462
    },

最后,我需要对LineLineStart的结果进行分组,但我认为我已经拥有了其他所有内容(我将日期减去小时,分钟,...来自我有约会。)

所以我唯一需要知道的是如何只计算我真正想要的数组元素。

我已阅读db.collection.group()

但我发现db.collection.group()方法不适用于分片群集,所以我无法使用它。

我也读过这个老问题: MongoDB: Count of matching nested array elements 这或多或少是相同的,但它差不多五年前回答,当时,答案是没有直接的方法去做,所以我要求现在有办法。< / p>

2 个答案:

答案 0 :(得分:3)

使用mongo聚合,你可以找到计数,检查下面的聚合查询

db.Lines.aggregate([
{
    "$unwind": "$SSCEXPEND"
},
{
    "$unwind": "$SSCVALIDATIONS"
},
{
    "$match": {
        "$and": [
            {
                "SSCEXPEND.Title": 1
            },
            {
                "SSCVALIDATIONS.Result": {
                    "$gt": 10
                }
            }
        ]
    }
},
{
    "$group": {
        "_id": "$_id",
        "SSCEXPEND": {
            "$addToSet": "$SSCEXPEND"
        },
        "SSCVALIDATIONS": {
            "$addToSet": "$SSCVALIDATIONS"
        },
        "SSCCANCELATIONS": {
            "$first": "$SSCCANCELATIONS"
        }
    }
},
{
    "$project": {
        "SSCEXPENDCOUNT": {
            "$size": "$SSCEXPEND"
        },
        "SSCVALIDATIONSCOUNT": {
            "$size": "$SSCVALIDATIONS"
        },
        "SSCCANCELATIONSCOUNT": {
            "$size": "$SSCCANCELATIONS"
        }
    }
}
]).pretty()

答案 1 :(得分:3)

带有展开的方法占用了大量资源。你可以直接使用项目

db.c.aggregate([
{
    $project: {
         _id: 1,
         Line: 1,
         LineStart:1,

         SSCEXPEND: {
            $size: {
                $filter: {
                   input: "$SSCEXPEND",
                   as: "e",
                   cond:{ $eq: [ "$$e.Title", 1 ]}
                }
            }
         },
         SSCCANCELATIONS: {
            $size: "$SSCCANCELATIONS"
         },
         SSCVALIDATIONS:{
            $size: {
               $filter: {
                   input: "$SSCVALIDATIONS",
                   as: "v",
                   cond: {$lt: [ "$$v.Result", 10 ]}
                }
            }
         }

      }
}
])

然后简单地让你的$ group获得所有SSCEXPEND,SSCCANCELATIONS等的总和......