繁体   English   中英

MongoDB(mongoose)聚合集合中特定ObjectID的计数实例

[英]MongoDB (mongoose) aggregate count instances of specific ObjectIDs in collection

假设我的模式看起来像这样:

{
    field: [{
        subDoc: ObjectId,
        ...
    }],
    ...
}

我有一些ObjectIds(用户输入)列表,我如何得到这些特定ObjectIds的计数? 例如,如果我有这样的数据:

[
    {field: [ {subDoc: 123}, {subDoc: 234} ]},
    {field: [ {subDoc: 234}, {subDoc: 345} ]},
    {field: [ {subDoc: 123}, {subDoc: 345}, {subDoc: 456} ]}
]

与用户给定ID列表是123, 234, 345 ,我需要得到一个数给定的ID,所以结果是近似的:

{
    123: 2,
    234: 2,
    345: 2
}

最好的方法是什么?

聚合框架本身如果不按照你提出的输出方式动态命名键,那真的是一件好事。 但你可以像这样做一个查询:

db.collection.aggregate([
    // Match documents that contain the elements
    { "$match": { 
        "field.subDoc": { "$in": [123,234,345] }
    }},

    // De-normalize the array field content
    { "$unwind": "$field" },

    // Match just the elements you want
    { "$match": { 
        "field.subDoc": { "$in": [123,234,345] }
    }},

    // Count by the element as a key
    { "$group": {
        "_id": "$field.subDoc",
        "count": { "$sum": 1 }
    }}
])

这给你输出如下:

{ "_id" : 345, "count" : 2 }
{ "_id" : 234, "count" : 2 }
{ "_id" : 123, "count" : 2 }

但是,如果您真的想要坚持这一点,那么您在查询中指定了所需的“键”,因此您可以形成如下管道:

db.collection.aggregate([
    { "$match": { 
        "field.subDoc": { "$in": [123,234,345] }
    }},
    { "$unwind": "$field" },
    { "$match": { 
        "field.subDoc": { "$in": [123,234,345] }
    }},
    { "$group": {
        "_id": "$field.subDoc",
        "count": { "$sum": 1 }
    }},
    { "$group": {
        "_id": null,
        "123": { 
            "$max": {
                "$cond": [
                    { "$eq": [ "$_id", 123 ] },
                    "$count",
                    0
                ]
            }
        },
        "234": { 
            "$max": {
                "$cond": [
                    { "$eq": [ "$_id", 234 ] },
                    "$count",
                    0
                ]
            }
        },
        "345": { 
            "$max": {
                "$cond": [
                    { "$eq": [ "$_id", 345 ] },
                    "$count",
                    0
                ]
            }
        }
    }}
])

通过处理参数列表,在代码中构造最后一个阶段是一件相对简单的事情:

var list = [123,234,345];

var group2 = { "$group": { "_id": null } };

list.forEach(function(id) {
    group2["$group"][id] = { 
        "$max": {
            "$cond": [
                { "$eq": [ "$_id", id ] },
                "$count",
                0
            ]
        }
    };
});

而这或多或少都是你想要的。

{ 
    "_id" : null, 
    "123" : 2, 
    "234" : 2, 
    "345" : 2 
}

不完全是你要求的,但它可以给你一个想法:

    db.test.aggregate([
    {
        $unwind: '$field'
    },
    {
        $group: {
            _id: {
                subDoc: '$field.subDoc'
            },
            count: {
                $sum: 1
            }
        }
    },
    {
        $project: {
            subDoc: '$subDoc.subDoc',
            count: '$count'
        }
    }
]);

输出:

 {
    "result": [
        {
            "_id": {
                "subDoc": 456
            },
            "count": 1
        },
        {
            "_id": {
                "subDoc": 345
            },
            "count": 2
        },
        {
            "_id": {
                "subDoc": 234
            },
            "count": 2
        },
        {
            "_id": {
                "subDoc": 123
            },
            "count": 2
        }
    ],
    "ok": 1
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM