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

Posted

技术标签:

【中文标题】MongoDB(猫鼬)聚合计数集合中特定 ObjectID 的实例【英文标题】:MongoDB (mongoose) aggregate count instances of specific ObjectIDs in collection 【发布时间】:2014-12-10 01:47:00 【问题描述】:

假设我有一个看起来像这样的架构:


    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

最好的方法是什么?

【问题讨论】:

【参考方案1】:

聚合框架本身如果不以您作为建议输出的方式动态命名键,那可能真的是一件好事。但你可能只需要这样查询:

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 

【讨论】:

【参考方案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

【讨论】:

以上是关于MongoDB(猫鼬)聚合计数集合中特定 ObjectID 的实例的主要内容,如果未能解决你的问题,请参考以下文章

将订单集合中的订单总和添加到猫鼬中的用户集合

计数字段包含具有聚合mongodb的集合中的数据

Mongodb聚合计数数组/集合大小

具有特定条件计数的 Mongodb 聚合并按输出投影的日期范围过滤不能按预期工作

使用 mongoDB 中的聚合删除集合中所有文档的特定字段

猫鼬跳过、限制和计数