MongoDB聚合管道组
我正在尝试构建一个管道,它将根据某些条件搜索文档,并将某些字段分组以提供所需的输出。MongoDB聚合管道组,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我正在尝试构建一个管道,它将根据某些条件搜索文档,并将某些字段分组以提供所需的输出。交易的文档结构是 { "_id":"123", "status":"New", "deal_amount":"5200", "deal_date":"2018-03-05", "data_source":"API", "deal_type":"New Business", "account_id":"A1" }, { "_id":"456", "status"
交易的文档结构是
{
"_id":"123",
"status":"New",
"deal_amount":"5200",
"deal_date":"2018-03-05",
"data_source":"API",
"deal_type":"New Business",
"account_id":"A1"
},
{
"_id":"456",
"status":"New",
"deal_amount":"770",
"deal_date":"2018-02-11",
"data_source":"API",
"deal_type":"New Business",
"account_id":"A2"
},
{
"_id":"885",
"status":"Old",
"deal_amount":"4070",
"deal_date":"2017-09-22",
"data_source":"API",
"deal_type":"New Business",
"account_id":"A2"
},
“帐户名”字段被引用。帐户文档如下所示:
{
"_id":"A1",
"name":"Sarah",
},
{
"_id":"A2",
"name":"Amber",
},
管道应搜索“状态”为“新”且“交易金额”大于2000的文档,并应按“账户名称”分组。我用过的管道是这样的
db.deal.aggregate([{
$match: {
status: New,
deal_amount: {
$gte: 2000,
}
}
}, {
$group: {
_id: "$account_name",
}
},{
$lookup:{
from:"accounts",
localField:"account_id",
foreignField:"_id",
as:"acc",
}
}
])
我只想在结果中显示交易金额、交易类型、交易日期和账户名称字段
预期结果:
{
"_id": "123",
"deal_amount": "5200",
"deal_date": "2018-03-05",
"deal_type": "New Business",
"account_name": "Sarah"
}, {
"_id": "885",
"deal_amount": "4070",
"deal_date": "2017-09-22",
"deal_type": "New Business",
"account_name": "Amber"
},
我是否必须在“分组”阶段包含所有这些字段、交易金额、交易类型、交易日期和账户名称,以便在结果中显示,或者是否有其他方法来显示。非常感谢您的帮助。首先,您的$gte
运算符无法处理字符串字段交易金额
,因此您可能需要将该字段更改为整数或类似的内容:
// Convert String to Integer
db.deals.find().forEach(function(data) {
db.deals.update(
{_id:data._id},
{$set:{deal_amount:parseInt(data.deal_amount)}});
然后,要仅获取所需的字段,请使用$project
重塑文档:
db.deals.aggregate([{
$match: {
"status": "New",
"deal_amount" : {
"$gte" : 2000
}
}
},
{
$lookup:{
from:"accounts",
localField:"account_id",
foreignField:"_id",
as:"acc",
}
},
{
$project: {
_id: 1,
deal_amount: 1,
deal_type: 1,
deal_date: 1,
"account_name": {"$let":{"vars":{"accl":{"$arrayElemAt":["$acc", 0]}}, in:"$$accl.name"}}
}
}
]);
对我来说,这产生了:
{
"_id" : "123",
"deal_amount" : 5200.0,
"deal_date" : "2018-03-05",
"deal_type" : "New Business",
"account_name" : "Sarah"
}
请使用此查询
aggregate([{
$match: {
status: "New",
deal_amount: {
$gte: 2000,
}
}
},
{
$lookup:{
from:"accounts",
localField:"account_id",
foreignField:"_id",
as:"acc",
}
},
{
$unwind: {
path: '$acc',
preserveNullAndEmptyArrays: true,
},
},
{
$group: {
_id: "$acc._id",
deal_amount: { $first: '$deal_amount' },
deal_date: { $first: '$deal_date' },
deal_type: { $first: '$deal_type' },
}
}
])
您可以通过以下方式完成:
1) 使用$$ROOT
参考:
2) 通过指定单个参数
{
$group: {
_id: "$account_name",
deal_amount: { $first: '$deal_amount' },
deal_date: { $first: '$deal_date' },
.
.
}
}
不确定为什么需要$group
阶段。您只需添加$project
阶段即可从引用的集合中输出帐户名
{
"$project": {
"deal_amount": 1,
"deal_type": 1,
"deal_date": 1,
"account_name": {"$let":{"vars":{"accl":{"$arrayElemAt":["$acc", 0]}}, in:"$$accl.name}}
}
}
您建议在管道中按顺序进行匹配、项目和查找阶段。谢谢Veeram,但选择order.Np的原因是什么。比赛总是第一位的。项目引用查找字段,以便在项目之前进行查找。假设在我的情况下,如果要进行分组,则顺序是$match、$group,然后是$lookup。这取决于组中使用的字段。如果不使用外部集合中的字段,则可以在查找之前进行,也可以在查找之后进行。
{
"$project": {
"deal_amount": 1,
"deal_type": 1,
"deal_date": 1,
"account_name": {"$let":{"vars":{"accl":{"$arrayElemAt":["$acc", 0]}}, in:"$$accl.name}}
}
}