首页 文章

对聚合中字段的最大值进行分组

提问于
浏览
1

假设我有2个字段 AB . 字段 A 可以采用以下值: [a,b,c,d,e] 和B: [x,y] .

我正在寻找一个MongoDB聚合管道查询,它将:

  • 计算 A 的每个值在我的数据库中出现的次数

  • 显示 A 的最近出现值 B 的值的分布

Example:

假设'c'恰好是A的最大值:

输出将是:

{ '_id': { 'A': 'c', 'B': 'x' }, 'count': 43 }
{ '_id': { 'A': 'c', 'B': 'y' }, 'count': 13 }

我设法做到这一点的唯一方法是将 A:c 硬编码到我的 "$match" 语句中 .

1 回答

  • 1

    您可以从输出中推断聚合管道 . _id 字段有两个键 AB ,它们推断出 $group 键由两个键组成,并且通过调用 $sum 累加器来获取计数 .

    Populate Test Collection

    假设我们使用以下文档生成测试集合

    db.collection.insert([
        { "A": "c", "B": "x" },
        { "A": "c", "B": "x" },
        { "A": "c", "B": "x" },
        { "A": "e", "B": "x" },
        { "A": "c", "B": "x" },
        { "A": "c", "B": "x" },
        { "A": "a", "B": "x" },
        { "A": "c", "B": "x" },
        { "A": "c", "B": "x" },
        { "A": "a", "B": "x" },
        { "A": "c", "B": "y" },
        { "A": "c", "B": "x" },
        { "A": "c", "B": "x" },
        { "A": "b", "B": "x" },
        { "A": "c", "B": "x" },
        { "A": "c", "B": "x" },
        { "A": "a", "B": "y" },
        { "A": "a", "B": "y" },
        { "A": "b", "B": "y" },
        { "A": "b", "B": "y" },
        { "A": "b", "B": "y" },
        { "A": "b", "B": "y" },
        { "A": "b", "B": "y" },
        { "A": "c", "B": "y" },
        { "A": "e", "B": "y" },
        { "A": "e", "B": "y" },
        { "A": "d", "B": "y" },
        { "A": "d", "B": "y" },
        { "A": "d", "B": "y" }
    ])
    

    然后,以下初始管道将对这两个键上的文档进行分组并获取计数:

    db.collection.aggregate([
        {
            "$group": {
                "_id": { "A": "$A", "B": "$B" },
                "count": { "$sum": 1 }
            }
        }
    ])
    

    Sample Output

    /* 1 */
    {
        "_id" : {
            "A" : "e",
            "B" : "y"
        },
        "count" : 2
    }
    
    /* 2 */
    {
        "_id" : {
            "A" : "c",
            "B" : "x"
        },
        "count" : 11
    }
    
    /* 3 */
    {
        "_id" : {
            "A" : "b",
            "B" : "y"
        },
        "count" : 5
    }
    
    /* 4 */
    {
        "_id" : {
            "A" : "b",
            "B" : "x"
        },
        "count" : 1
    }
    
    /* 5 */
    {
        "_id" : {
            "A" : "e",
            "B" : "x"
        },
        "count" : 1
    }
    
    /* 6 */
    {
        "_id" : {
            "A" : "d",
            "B" : "y"
        },
        "count" : 3
    }
    
    /* 7 */
    {
        "_id" : {
            "A" : "a",
            "B" : "y"
        },
        "count" : 2
    }
    
    /* 8 */
    {
        "_id" : {
            "A" : "a",
            "B" : "x"
        },
        "count" : 2
    }
    
    /* 9 */
    {
        "_id" : {
            "A" : "c",
            "B" : "y"
        },
        "count" : 2
    }
    

    从观察来看,具有计数11的文档#2具有“c”作为最大值:

    /* 2 */
    {
        "_id" : {
            "A" : "c",
            "B" : "x"
        },
        "count" : 11
    }
    

    到目前为止,您可以进一步聚合以获得最重要的密钥 . 您需要另一个 $group 管道,它将通过 A 键对前一个管道的结果进行分组,创建一个包含文档详细信息的列表,即计数和相应的 B 值 . 您还需要每组 A 值的计数字段:

    db.collection.aggregate([
        {
            "$group": {
                "_id": { "A": "$A", "B": "$B" },
                "count": { "$sum": 1 }
            }
        },
        {
            "$group": {
                "_id": "$_id.A",
                "counts": {
                    "$push": {
                        "B": "$_id.B",
                        "count": "$count"
                    }
                },
                "count": { "$sum": "$count" } 
            }
        }
    ])
    

    Sample Output

    /* 1 */
    {
        "_id" : "e",
        "counts" : [ 
            {
                "B" : "y",
                "count" : 2
            }, 
            {
                "B" : "x",
                "count" : 1
            }
        ],
        "count" : 3
    }
    
    /* 2 */
    {
        "_id" : "c",
        "counts" : [ 
            {
                "B" : "x",
                "count" : 11
            }, 
            {
                "B" : "y",
                "count" : 2
            }
        ],
        "count" : 13
    }
    
    /* 3 */
    {
        "_id" : "b",
        "counts" : [ 
            {
                "B" : "y",
                "count" : 5
            }, 
            {
                "B" : "x",
                "count" : 1
            }
        ],
        "count" : 6
    }
    
    /* 4 */
    {
        "_id" : "d",
        "counts" : [ 
            {
                "B" : "y",
                "count" : 3
            }
        ],
        "count" : 3
    }
    
    /* 5 */
    {
        "_id" : "a",
        "counts" : [ 
            {
                "B" : "y",
                "count" : 2
            }, 
            {
                "B" : "x",
                "count" : 2
            }
        ],
        "count" : 4
    }
    

    在此阶段,您只需要对计数字段中的文档进行排序,并在按降序排列文档时返回顶部文档:

    db.collection.aggregate([
        {
            "$group": {
                "_id": { "A": "$A", "B": "$B" },
                "count": { "$sum": 1 }
            }
        },
        {
            "$group": {
                "_id": "$_id.A",
                "counts": {
                    "$push": {
                        "B": "$_id.B",
                        "count": "$count"
                    }
                },
                "count": { "$sum": "$count" }
            }
        },
        { "$sort": { "count": -1 } },
        { "$limit": 1 }
    ])
    

    产量:

    {
        "_id" : "c",
        "counts" : [ 
            {
                "B" : "x",
                "count" : 11
            }, 
            {
                "B" : "y",
                "count" : 2
            }
        ],
        "count": 13
    }
    

    虽然输出与所需的结构不同,但它仍然足以解决问题

    1. 计算 A 的每个值在我的数据库中出现的次数 - >所需的管道:

    db.collection.aggregate([
        {
            "$group": {
                "_id": { "A": "$A", "B": "$B" },
                "count": { "$sum": 1 }
            }
        },
        {
            "$group": {
                "_id": "$_id.A",                
                "count": { "$sum": "$count" }
            }
        }
    ])
    

    2. 显示最大值A的 B 值的分布

    db.collection.aggregate([
        {
            "$group": {
                "_id": { "A": "$A", "B": "$B" },
                "count": { "$sum": 1 }
            }
        },
        {
            "$group": {
                "_id": "$_id.A",
                "counts": {
                    "$push": {
                        "B": "$_id.B",
                        "count": "$count"
                    }
                },
                "count": { "$sum": "$count" }
            }
        },
        { "$sort": { "count": -1 } },
        { "$limit": 1 }
    ])
    

相关问题