MongoDB 聚合两个集合,返回附加字段作为计数
Posted
技术标签:
【中文标题】MongoDB 聚合两个集合,返回附加字段作为计数【英文标题】:MongoDB aggregate two collections, return additional field as count 【发布时间】: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"
])
【问题讨论】:
【参考方案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 但我不推荐,最好你处理这种问题客户端。
【讨论】:
感谢您的回答 - 我刚刚使用我在这里找到的汇总示例更新了对该问题的第二次编辑:***.com/questions/44888354/… 这种方法有问题吗? 我不知道聚合管道中的管道!看起来是个不错的方法!以上是关于MongoDB 聚合两个集合,返回附加字段作为计数的主要内容,如果未能解决你的问题,请参考以下文章