首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >滤波$lookup结果

滤波$lookup结果
EN

Stack Overflow用户
提问于 2016-06-15 11:12:53
回答 2查看 6.3K关注 0票数 2

我有两个集合(带有示例文档):

报告

代码语言:javascript
复制
{
    id: "R1",
    type: "xyz",
}

报告文件

代码语言:javascript
复制
{
    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,因为它将是冗余的)。

代码语言:javascript
复制
{
    id: "R1",
    type: "xyz",
    reportfile: {
        id: "F14",
        reportid: "R1",
        time: ISODate("2016-06-15T09:20:29.809Z")
    }
}

这里的问题是,每个报表类型都有自己的属性集,因此在聚合管道中使用$project不是最好的方法。

到目前为止

代码语言:javascript
复制
db.reports.aggregate([{
            $match : 'R1'
        }, {
            $lookup : {
                from : 'reportfiles',
                localField : 'id',
                foreignField : 'reportid',
                as : 'reportfile'
            }
        }
    ])

当然,返回为“reportfile”的所有文件的列表与给定的reportid。如何有效地过滤该列表以获得我所需的唯一元素?

高效地使用->,我尝试使用$unwind作为下一个管道步骤,但是得到的文档长得令人生畏,毫无意义。

谢谢您的建议!

EN

回答 2

Stack Overflow用户

发布于 2016-06-15 12:01:10

您需要将另一个$project阶段添加到$lookup阶段之后的聚合管道中。

代码语言:javascript
复制
{ "$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轻松地访问结果中所需的字段。

票数 2
EN

Stack Overflow用户

发布于 2016-06-15 12:00:47

您需要的是在reportfile集合上运行聚合操作,对reports集合执行“联接”,将$group操作从$lookup管道输送到ordered (使用$sort)和扁平的文档(使用$unwind)。然后,可以由reportid对前面的结果进行分组,并使用$first累加器aoperators输出所需的结果。

以下说明了这一做法:

代码语言:javascript
复制
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"
                }
            }
        }
    }
])

示例输出:

代码语言:javascript
复制
{
    "_id" : "R1",
    "type" : "xyz",
    "reportfile" : {
        "id" : "F14",
        "reportid" : "R1",
        "time" : ISODate("2016-06-15T09:20:29.809Z")
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37833808

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档