繁体   English   中英

MongoDB聚合两个集合,返回其他字段作为计数

[英]MongoDB aggregate two collections, return additional field as count

(请参见下面的编辑)

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

“帐户”集合包含用户信息(已清除):

{ 
    _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 } } }
     ])

2nd编辑16/12:

我发现以下需要的汇总:

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

首先,可以使用如下所示的投影来展平答案:

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

将其添加到管道中的$ group之后,您将获得所需的结果。

关于零计数用户,有一种方法可以使用mongoDB在数据库中处理此问题,如此处详细说明但我不建议这样做,因为最好是处理此类问题的客户端。

每秒编辑一次,我使用的汇总如下:

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

暂无
暂无

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

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