mongodb - MongoDB - 加入两个查询结果和dense_rank
问题描述
我正在学习 MongoDB,但在理解它的概念时遇到了一些问题。
我有一个看起来像这样的集合:
db.email.findOne()
{
"_id" : ObjectId("52af48b5d55148fa0c199646"),
"sender" : "tori.wells@enron.com",
"recipients" : [
"michael@optsevents.com"
],
"cc" : [ ],
"text" : "Mr. Christman:\n\nThank you for your invitation for Dr. Lay to speak at your upcoming forum in \nFrance, the format looks wonderful. Unfortunately, Dr. Lay has calendar \nconflicts and will be unable to participate.\n\nIf you should need further assistance, please do not hesitate to contact us.\n\nTori Wells\nExecutive Assistant",
"mid" : "22263156.1075840285610.JavaMail.evans@thyme",
"fpath" : "enron_mail_20110402/maildir/lay-k/_sent/101.",
"bcc" : [ ],
"to" : [
"michael@optsevents.com"
],
"replyto" : null,
"ctype" : "text/plain; charset=us-ascii",
"fname" : "101.",
"date" : "2000-08-04 09:04:00-07:00",
"folder" : "_sent",
"subject" : "Wall Street Journal Millennium Forum"
}
这是安然数据库。
我正在尝试进行查询,该查询将返回列出的电子邮件,其中包含它发送的消息数量和接收的消息数量。
我设法进行了两个查询,如下所示:
db.email.aggregate({$group:{_id:"$sender",SendsAmount:{$sum:1}}},{$sort:{SendsAmount:-1}})
{ "_id" : "rosalee.fleming@enron.com", "SendsAmount" : 849 }
{ "_id" : "brown_mary_jo@lilly.com", "SendsAmount" : 82 }
{ "_id" : "leonardo.pacheco@enron.com", "SendsAmount" : 78 }
db.email.aggregate({$group:{_id:"$recipients",ReceivedAmount:{$sum:1}}},{$unwind:"$_id"},{$sort:{ReceivedAmount:-1}})
{ "_id" : "klay@enron.com", "ReceivedAmount" : 1350 }
{ "_id" : "kenneth.lay@enron.com", "ReceivedAmount" : 912 }
{ "_id" : "kenneth.lay@enron.com", "ReceivedAmount" : 78 }
如您所见,第一个返回给我的电子邮件和从它发送的电子邮件数量,第二个也返回电子邮件和它收到的电子邮件数量。
我的意思是将(?)这两个合二为一,并获得一个查询,该查询将返回如下内容:
{ "_id" : "email@enron.com", "SendsAmount" : 57, "ReceivedAmount": 43 }
我知道有 $lookup 但它只能用于两个集合,所以我的想法是从这两个查询中创建两个集合,但我觉得有更好的方法来解决我的问题。
---我的第二个问题是关于尝试做一些 MongoDB 中不存在的 DENSE_RANK。我想按已发送电子邮件的数量对电子邮件地址进行排名。
我使用了 $unwind 和 insertArrayIndex 但我得到了类似 ROW_NUMBER 的东西,这不是我想要的。
我写过这样的东西:
db.email.aggregate({$group:{"_id":"$sender",SendsAmount:{$sum:1},rank:0}},{$sort:{"ile":-1}}).forEach(function(x){
var howmany=0;
var query=db.email.aggregate({$group:{"_id":"$sender",SendsAmount:{$sum:1}}},{$match:{ile:{$gt:x.SendsAmount}}},{$group:{_id:null, HowManyGreater:{$sum:1}}});
query.forEach(function(y){
howmany=y.HowManyGreater;
});
howmany=howmany+1;
print("email: "+ x._id + " SendsAmount: " + x.SendsAmount + " rank " + howmany+1);
});
这给了我想要的结果,但它甚至不是文档,而只是打印的信息。我已经阅读了 MapReduce,但我不知道在这种情况下如何使用它。
解决方案
如果要在聚合查询中进行所有计算,可以使用 $facet 和 $group 阶段,如下所示
db.email.aggregate([
{
$facet: {
send: [
{
$group: {
_id: "$sender",
SendsAmount: {
$sum: 1
}
}
},
{
$sort: {
SendsAmount: -1
}
}
],
recieve: [
{
$group: {
_id: "$recipients",
ReceivedAmount: {
$sum: 1
}
}
},
{
$unwind: "$_id"
},
{
$sort: {
ReceivedAmount: -1
}
}
]
}
},
{
$project: {
all: {
$concatArrays: [
"$recieve",
"$send"
]
}
}
},
{
$unwind: "$all"
},
{
$group: {
_id: "$all._id",
ReceivedAmount: {
$sum: {
$cond: {
if: {
$gt: [
"$all.ReceivedAmount",
null
]
},
then: "$all.ReceivedAmount",
else: 0
}
}
},
SendsAmount: {
$sum: {
$cond: {
if: {
$gt: [
"$all.SendsAmount",
null
]
},
then: "$all.SendsAmount",
else: 0
}
}
}
}
}
])
推荐阅读
- blazor-server-side - Blazor:如何在启动时有条件地将用户重定向到另一个页面?
- python - 检查 lambda 函数的主体
- ios - 如何在 Swift 中将本地文件路径 url 更改为本地主机 url
- javascript - 如何根据父 div 元素调整画布大小(反应)?
- flutter - 如何在 Flutter 中计算并获取两年之间的月份列表?
- python - Jupyter 实验室提示输入令牌;我怎么找到它?
- javascript - 在 Strapi.io 中实施审计跟踪/日志
- excel - VBA excel打开文件并复制工作表错误下标超出范围
- c# - 如何从 appsettings.json 文件中获取 ConnectionString?
- apple-music - 通过 Facebook Messenger 应用内浏览器授权 Apple Music