我有 2 个集合(带有示例文档):
报告
{
id: "R1",
type: "xyz",
}
报告文件
{
id: "F1",
reportid: "R1",
time: ISODate("2016-06-13T14:20:25.812Z")
},
{
id: "F14",
reportid: "R1",
time: ISODate("2016-06-15T09:20:29.809Z")
}
如您所见,一份报告
可能有多个报告文件
。
我想执行查询,匹配报告 id
,按原样返返回告文档,再加上一个附加键,将 reportfile
存储为子文档,其中包含最多的内容最近的时间
(没有reportid
就更好了,因为它是多余的),例如
{
id: "R1",
type: "xyz",
reportfile: {
id: "F14",
reportid: "R1",
time: ISODate("2016-06-15T09:20:29.809Z")
}
}
我的问题是,每种报表类型都有自己的一组属性,因此在聚合管道中使用 $project
并不是最好的方法。
到目前为止我已经得到了
db.reports.aggregate([{
$match : 'R1'
}, {
$lookup : {
from : 'reportfiles',
localField : 'id',
foreignField : 'reportid',
as : 'reportfile'
}
}
])
当然会以“reportfile”形式返回具有给定reportid
的所有文件的列表。如何有效地过滤该列表以获得我需要的唯一元素?
高效 -> 我尝试使用 $unwind
作为下一个管道步骤,但生成的文档长得可怕且毫无意义。
预先感谢您的任何建议!
最佳答案
您需要添加另一个 $project
$lookup
之后阶段到聚合管道阶段。
{ "$project": {
"id": "R1",
"type": "xyz",
"reportfile": {
"$let": {
"vars": {
"obj": {
"$arrayElemAt": [
{ "$filter": {
"input": "$reportfile",
"as": "report",
"cond": { "$eq": [ "$$report.time", { "$max": "$reportfile.time" } ] }
}},
0
]
}
},
"in": { "id": "$$obj.id", "time": "$$obj.time" }
}
}
}}
$filter
运算符“过滤”$lookup
结果并返回一个包含满足条件的文档的数组。这里的条件是$eq
当文档具有 $max
时返回 true最低值。
$arrayElemAt
运算符切片 $filter 的结果并返回数组中的元素,然后使用 $let
将其分配给变量运算符(operator)。从那里,您可以使用 dot notation 轻松访问结果中所需的字段。 .
关于mongodb - 过滤$lookup结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37833808/