Mongodb 聚合后如何取回原始文档

Mongodb 聚合后如何取回原始文档,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我有一个例子,我想查询一组文档,这些文档在一个数组字段forms下有许多项。要解决的问题是希望只返回所有文档都包含在特定状态为“已关闭”的表单中的文档 db.forms.aggregate([ {$unwind: "$forms" }, {$group: { _id: "$_id", status: {$addToSet: "$forms.status" }}}, {$unwind: "$status"}, {$sort: { _id: 1, status: -1

我有一个例子,我想查询一组文档,这些文档在一个数组字段forms下有许多项。要解决的问题是希望只返回所有文档都包含在特定状态为“已关闭”的表单中的文档

db.forms.aggregate([
    {$unwind: "$forms" },
    {$group: { _id: "$_id", status: {$addToSet: "$forms.status" }}},
    {$unwind: "$status"},
    {$sort: { _id: 1, status: -1 }},
    {$group: {_id: "$_id", status: {$first: "$status"}}},
    {$match:{ status: "closed" }}
])
因此,以下是该系列中两个不同文档的示例:

{
    "_id" : "Tvq444454j",
    "name" : "Jim",
    "forms" : [
        {
            "name" : "Jorney",
            "status" : "closed"
        },
        {
            "name" : "Women",
            "status" : "void"
        },
        {
            "name" : "Child",
            "status" : "closed"
        },
        {
            "name" : "Farm",
            "status" : "closed"
        }
    ]
},

{
    "_id" : "Tvq579754r",
    "name" : "Tom",
    "forms" : [
        {
            "name" : "PreOp",
            "status" : "closed"
        },
        {
            "name" : "Alert",
            "status" : "closed"
        },
        {
            "name" : "City",
            "status" : "closed"
        },
        {
            "name" : "Country",
            "status" : "closed"
        }
    ]
}
预期的结果是:

{
    "_id" : "Tvq579754r",
    "name" : "Tom",
    "forms" : [
        {
            "name" : "PreOp",
            "status" : "closed"
        },
        {
            "name" : "Alert",
            "status" : "closed"
        },
        {
            "name" : "City",
            "status" : "closed"
        },
        {
            "name" : "Country",
            "status" : "closed"
        }
    ]
}
由于在这种情况下没有标准的查询运算符来匹配数组的所有元素,因此使用聚合找到了解决方案。这将返回集合中所有表单元素都设置为关闭状态的文档的_id

db.forms.aggregate([
    {$unwind: "$forms" },
    {$group: { _id: "$_id", status: {$addToSet: "$forms.status" }}},
    {$unwind: "$status"},
    {$sort: { _id: 1, status: -1 }},
    {$group: {_id: "$_id", status: {$first: "$status"}}},
    {$match:{ status: "closed" }}
])
因此,由于我希望在结果中返回许多文档,我希望避免发出另一个find或一系列find来获取与返回的id匹配的文档


考虑到这一点,有没有什么方法可以让我以与集合中完全相同的形式从聚合中获取原始文档,同时仍在进行这种类型的过滤?

属于愚蠢的聚合技巧范畴是一种经常被忽略的小技巧

执行所有操作的查询都围绕文档id进行分组,文档id是该文档的唯一标识符。因此,需要考虑的主要问题是,整个文档实际上已经是一个唯一的标识符。因此,使用整个文档,而不是仅仅存储在_id键中

    {$project: { 
        _id: { _id: "$_id", name: "$name", forms: "$forms" }, forms: "$forms"}
    },
在执行此操作时,由_id汇总的任何内容都将以原始形式保留文档。在所有其他聚合阶段结束时,发布最终版本以恢复真实的原始文档表单:

    {$project: { _id: "$_id._id", name: "$_id.name", forms: "$_id.forms"}}
然后您将得到所需的过滤结果。当与高级过滤一起使用时(例如在这个查询中),这种技术非常方便,因为它不需要对所有结果发出额外的查找

此外,在这种情况下,如果您知道您只在寻找一组将匹配某一组条件的结果,请使用运算符作为聚合管道的第一阶段。这不仅有助于减少工作集的大小,而且也是可以使用索引和显著提高查询性能的唯一阶段

整个过程包括:

db.forms.aggregate([
    {$match: { "forms.status": "closed" } },
    {$project: { 
        _id: { _id: "$_id", name: "$name", forms: "$forms" }, forms: "$forms"}
    },
    {$unwind: "$forms"},
    {$group: { _id: "$_id", status: {$addToSet: "$forms.status"}}},
    {$unwind: "$status"},
    {$sort: { _id: 1, status: -1} },
    {$group: { _id: "$_id", status: {$first: "$status"} }},
    {$match: { status: "closed"}},
    {$project: { _id: "$_id._id", name: "$_id.name", forms: "$_id.forms"}}
])

应该很快会有一个*或某个操作符能够在聚合中以完整形式返回原始文档pipeline@Sammaye我相信您指的是$$ROOT,它有不同的用途,但可以在这里使用。这应该在版本2.6中提供。这是一种现在可以使用的技巧,但可能很多人都无法使用。嗨@NeilLunn我不知道你是谁,但我一直在阅读你的所有答案,并从中学到了很多东西,但从你被阻止的时候起,我停了下来,什么也学不到。有一个问题你是来这里赢取积分的吗?从我的想法来看,不。你来这里是为了帮助别人。阻止你不是你曾经帮助过的人的过错。至少请回答那些需要你的人。所以,请再来或者帮助我,或者至少回复我。你的信是忠实的。希望您再次光临:-