【问题标题】:MongoDB aggregate two collections, return additional field as countMongoDB 聚合两个集合,返回附加字段作为计数
【发布时间】:2019-05-16 15:50:51
【问题描述】:

(请参阅下面的编辑)

我正在尝试从同一个 MongoDB 数据库中的两个单独集合中聚合数据。

“accounts”集合包含用户信息(已清理):

{ 
    _id: ObjectId("5c0d64a4224a2900108c005f"),
    "username" : "mike22", 
    "email" : "mike22@<domain>.com",
    "country" : GB,
    "created" : ISODate("2018-11-26T23:37:49.051Z") 
},
{ 
    _id: ObjectId("5a0d64a4527h2880108c0445"),
    "username" : "mike23", 
    "email" : "mike23@<domain>.com", 
    "country" : DE,
    "created" : ISODate("2018-11-26T23:37:49.051Z")
},
{ 
    _id: ObjectId("5a3334a45zzz2884448c0445"),
    "username" : "mike24", 
    "email" : "mike24@<domain>.com", 
    "country" : DE,
    "created" : ISODate("2018-11-26T23:37:49.051Z")
}

“设备”集合包含所有用户的设备定义。用户可能在此集合中定义了许多设备,并且许多用户设备在此集合中。

此集合中的单个设备定义如下:

{ 
    "_id" : ObjectId("5c10138c73bbe0001018e415"), 
    "capabilities" : [ 
        "BrightnessController", 
        "PowerController" 
    ], 
    "displayCategories" : [ 
        "LIGHT" 
    ], 
    "friendlyName" : "Test1", 
    "description" : "Test device 1", 
    "reportState" : true, 
    "username" : "mike22", 
    "endpointId" : 11, 
    "__v" : 0 
},
{ 
    "_id" : ObjectId("5c10138c73bbe0001018e415"), 
    "capabilities" : [ 
        "PowerController" 
    ], 
    "displayCategories" : [ 
        "SWITCH" 
    ], 
    "friendlyName" : "Test2", 
    "description" : "Test device 2", 
    "reportState" : true, 
    "username" : "mike23", 
    "endpointId" : 12, 
    "__v" : 0 
},
{ 
    "_id" : ObjectId("5c10138c73bbe0001018e415"), 
    "capabilities" : [ 
        "PowerController" 
    ], 
    "displayCategories" : [ 
        "SMARTPLUG" 
    ], 
    "friendlyName" : "Test3", 
    "description" : "Test device 3", 
    "reportState" : true, 
    "username" : "mike22", 
    "endpointId" : 13, 
    "__v" : 0 
}

我可以使用下面的汇总来显示每位用户的设备数量:

db.accounts.aggregate([
    { 
        $lookup: {
            from : "devices",
            localField : "username",
            foreignField : "username",
            as : "userdevs"
        },
    },
    { $unwind:"$userdevs" },
    { $group : { _id : "$username", count : { $sum : 1 } } }
 ])

上述数据/聚合的示例输出:

{ "_id" : "mike22", "count" : 2 },
{ "_id" : "mike23", "count" : 1 }

(注意没有设备的用户现在丢失/应该为零计数?!)

但是,我想返回每个用户的所有字段加上一个新字段,该字段向我显示他们在“设备”集合中拥有的设备数量。我正在寻找的输出如下:

{ 
    "_id" : ObjectId("5c0d64a4224a2900108c005f"),
    "username" : "mike22", 
    "email" : "mike22@<domain>.com",
    "country" : GB,
    "created" : ISODate("2018-11-26T23:37:49.051Z"),
    "countDevices": 2
},
{ 
    "_id" : ObjectId("5a0d64a4527h2880108c0445"),
    "username" : "mike23", 
    "email" : "mike23@<domain>.com", 
    "country" : DE,
    "created" : ISODate("2018-11-26T23:37:49.051Z"),
    "countDevices": 1
},
{ 
    "_id" : ObjectId("5a0d64a4527h2880108c0445"),
    "username" : "mike24", 
    "email" : "mike24@<domain>.com", 
    "country" : DE,
    "created" : ISODate("2018-11-26T23:37:49.051Z"),
    "countDevices": 0
}

编辑 16/12: 所以我已经接近了下面的汇总。但零计数用户不见了。

use users
    db.accounts.aggregate([
        { 
            $lookup: {
                from : "devices",
                localField : "username",
                foreignField : "username",
                as : "userdevs"
            },
        },
        { $unwind: "$userdevs"},
        { $group : { _id : {
            _id: "$_id",
            username: "$username",
            email: "$email",
            country: "$country",
            region: "$region",
        },
        countDevices : { $sum : 1 } } }
     ])

2012 年 16 月第二次编辑:

我在下面找到了所需的聚合:

db.accounts.aggregate([
  { "$lookup": {
    "from": "devices",
    "let": { "username": "$username" },
    "pipeline": [
      { "$match": {
        "$expr": { "$eq": [ "$$username", "$username" ] }
      }},
      { "$count": "count" }
    ],
    "as": "deviceCount"    
  }},
  { "$addFields": {
    "countDevices": { "$sum": "$deviceCount.count" }
  }}
])

【问题讨论】:

    标签: mongodb aggregate


    【解决方案1】:

    按秒编辑,我使用的聚合如下:

    db.accounts.aggregate([
      { "$lookup": {
        "from": "devices",
        "let": { "username": "$username" },
        "pipeline": [
          { "$match": {
            "$expr": { "$eq": [ "$$username", "$username" ] }
          }},
          { "$count": "count" }
        ],
        "as": "deviceCount"    
      }},
      { "$addFields": {
        "countDevices": { "$sum": "$deviceCount.count" }
      }}
    ])
    

    【讨论】:

      【解决方案2】:

      首先,您可以使用如下投影来展平您得到的答案:

      { $project : {
              _id : '$_id._id',
              username : '$_id.username',
              email : '$_id.email',
              country : '$_id.country',
              region : '$_id.region',
              countDevices: 1
          }
      }
      

      在管道中的 $group 之后添加它,您将获得问题中想要的结果。

      关于零计数用户,有一种方法可以在数据库中使用 mongoDB 来处理这个问题,详细解释 here 但我不推荐,最好你处理这种问题客户端。

      【讨论】:

      • 感谢您的回答 - 我刚刚使用我在这里找到的汇总示例更新了对该问题的第二次编辑:stackoverflow.com/questions/44888354/… 这种方法有问题吗?
      • 我不知道聚合管道中的管道!看起来是个不错的方法!
      猜你喜欢
      • 2021-06-26
      • 2021-12-16
      • 2020-06-13
      • 2020-12-10
      • 1970-01-01
      • 2017-07-13
      • 2015-05-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多