【问题标题】:Grouping documents by an array, treat array as a set按数组对文档进行分组,将数组视为一个集合
【发布时间】:2016-03-25 12:26:42
【问题描述】:

我想使用 MongoDB 的聚合管道来完成一个听起来相当简单的任务。我想将一个字段中的数组视为集合(即,忽略顺序和重复),并按它们分组。例如,集合可能是:

[
    {
        _id: 1
        names: ["a", "b"]
    },
    {
        _id: 2
        names: ["c", "a"]
    },
    {
        _id: 3
        names: ["b", "a"]
    }
]

我想要返回的结果是这样的:

[
    {
        names: ["a", "b"],
        count: 2
    },
    {
        names: ["a", "c"],
        count: 1
    }
]

谢谢!

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    您需要$sort 结果以使它们对于分组键保持一致。真的没有别的办法了:

    db.collection.aggregate([
        { "$unwind": "$names" },
        { "$sort": { "_id": 1, "names": 1} },
        { "$group": {
            "_id": "$_id",
            "names": { "$push": "$names" }
        }},
        { "$group": {
            "_id": "$names",
            "count": { "$sum": 1 }
        }}
    ])
    

    按照您的要求返回:

    [
        {
            "_id": ["a", "b"],
            "count": 2
        },
        {
            "_id": ["a", "c"],
            "count": 1
        }
    ]
    

    虽然有很多运算符可以像“sets”这样在数组上工作,但它们都没有将数组内容“重新排序”为可在分组时应用的一致方式。仅当您 $sort 时才会这样做。

    即使数组包含“重复项”,并且应用了一些集合转换,它们的顺序仍然不一致:

    db.testa.insert_many([
        { "a" : [ "a", "b" ] },
        { "a" : [ "b", "a" ] },
        { "a" : [ "b", "a", "a" ] }
    ])
    
    db.testa.aggregate({ "$project": { "_id": 0, "a": { "$setUnion": [ "$a", [] ] } } })
    

    该样本当然会返回:

    { "a" : [ "b", "a" ] }
    { "a" : [ "a", "b" ] }
    { "a" : [ "a", "b" ] }
    

    因此,您“仍然”需要 $unwind$sort 以获得一致的“集合”以用于分组目的。

    【讨论】:

      【解决方案2】:

      您绝对可以通过将多个聚合管道拼接在一起来获得结果。

      db.collection.aggregate([
       {$unwind:"$names"},
       {$sort:{_id:1, names:1}},
       {$group:{_id:"$_id", names:{$push:"$names"}}},
       {$group:{_id:"$names", count:{$sum:1}}},
       {$project:{_id:0, names:"$_id", count:1}}
      ])
      

      它发出:

      { 
          "count" : NumberInt(1), 
          "names" : [
              "a", 
              "c"
          ]
      }
      { 
          "count" : NumberInt(2), 
          "names" : [
              "a", 
              "b"
          ]
      }
      

      【讨论】:

        猜你喜欢
        • 2021-05-05
        • 2018-02-19
        • 2017-10-04
        • 2021-12-17
        • 2018-09-17
        • 2023-04-09
        • 2017-03-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多