我有两个集合(带有示例文档):
报告
{
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")
}如您所见,一个report可能有多个reportfiles。
我想要执行一个查询,匹配一个报表id,按原样返回报告文档,再加上一个附加的键,将reportfile存储为带有最新time的子文档(更好的方法是没有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作为下一个管道步骤,但是得到的文档长得令人生畏,毫无意义。
谢谢您的建议!
发布于 2016-06-15 12:01:10
您需要将另一个$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,它在文档具有$maximum值时返回true。
$arrayElemAt运算符将$filter的结果切片,并从数组中返回元素,然后使用$let运算符分配给变量。从那里,您可以使用https://docs.mongodb.com/manual/core/document/#dot-notation轻松地访问结果中所需的字段。
发布于 2016-06-15 12:00:47
您需要的是在reportfile集合上运行聚合操作,对reports集合执行“联接”,将$group操作从$lookup管道输送到ordered (使用$sort)和扁平的文档(使用$unwind)。然后,可以由reportid对前面的结果进行分组,并使用$first累加器aoperators输出所需的结果。
以下说明了这一做法:
db.reportfiles.aggregate([
{ "$match": { "reportid": "R1" } },
{
"$lookup": {
"from": 'reports',
"localField" : 'reportid',
"foreignField" : 'id',
"as": 'report'
}
},
{ "$unwind": "$report" },
{ "$sort": { "time": -1 } },
{
"$group": {
"_id": "$reportid",
"type": { "$first": "$report.type" },
"reportfile": {
"$first": {
"id": "$id",
"reportid": "$reportid",
"time": "$time"
}
}
}
}
])示例输出:
{
"_id" : "R1",
"type" : "xyz",
"reportfile" : {
"id" : "F14",
"reportid" : "R1",
"time" : ISODate("2016-06-15T09:20:29.809Z")
}
}https://stackoverflow.com/questions/37833808
复制相似问题