【问题标题】:findOne then findMany using value from document found in findOne, in a single queryfindOne 然后 findMany 在单个查询中使用 findOne 中找到的文档中的值
【发布时间】:2021-06-18 00:29:58
【问题描述】:
const categorySlug = req.query.category;
const category = await Category.findOne({ slug: categorySlug });
const children = await Category.find({ parent: category._id });

是否可以将这两个查询合并为一个?我尝试做类似的事情

const children = await Category.aggregate([
      {
        $match: {
          slug: categorySlug, 
        },
      },
      {
        // somehow use the _id field from document fetched in first stage 
      }
    ]);

但我不知道这是否可能。

编辑:

const document = await Category.aggregate([
      {
        $match: {
          slug: categorySlug,
        },
      },
      {
        $lookup: {
          from: 'categories',
          localField: '_id',
          foreignField: 'parent',
          as: 'children',
        },
      },
    ]);

    const desiredResult = document[0].children;

这可行,但有没有办法在聚合管道中完全做到这一点?基本上我只想得到“孩子”数组,没有别的。

EDIT2:上述查询的结果是这个数组,其中一个对象包含一个对象数组

[
    {
        "_id": "6051cacf8f974b3104715ec4",
        "parent": null,
        "products": [
            "60515150d6ac5e08a4e796b4",
            "6051b8b0f8c80835480b28d3"
        ],
        "isParent": true,
        "name": "Electronics",
        "description": "All kinds of devices",
        "createdAt": "2021-03-17T09:24:31.365Z",
        "updatedAt": "2021-03-20T20:42:50.699Z",
        "slug": "electronics",
        "__v": 4,
        "children": [
            {
                "_id": "6051cb588f974b3104715ec5",
                "parent": "6051cacf8f974b3104715ec4",
                "products": [],
                "isParent": true,
                "name": "Cameras",
                "description": "description",
                "createdAt": "2021-03-17T09:26:48.220Z",
                "updatedAt": "2021-03-17T09:29:35.608Z",
                "slug": "cameras",
                "__v": 0
            },
            {
                "_id": "6051cb5f8f974b3104715ec6",
                "parent": "6051cacf8f974b3104715ec4",
                "products": [
                    "60515150d6ac5e08a4e796b4",
                    "6051b8b0f8c80835480b28d3"
                ],
                "isParent": true,
                "name": "Computers",
                "description": "description",
                "createdAt": "2021-03-17T09:26:55.364Z",
                "updatedAt": "2021-03-20T20:42:50.779Z",
                "slug": "computers",
                "__v": 4
            },
            {
                "_id": "6051cb6f8f974b3104715ec7",
                "parent": "6051cacf8f974b3104715ec4",
                "products": [],
                "isParent": false,
                "name": "Car Electronics",
                "description": "description",
                "createdAt": "2021-03-17T09:27:11.108Z",
                "updatedAt": "2021-03-17T09:27:11.108Z",
                "slug": "car-electronics",
                "__v": 0
            },
            {
                "_id": "6051cb768f974b3104715ec8",
                "parent": "6051cacf8f974b3104715ec4",
                "products": [],
                "isParent": false,
                "name": "TV",
                "description": "description",
                "createdAt": "2021-03-17T09:27:18.422Z",
                "updatedAt": "2021-03-17T09:27:18.422Z",
                "slug": "tv",
                "__v": 0
            }
        ]
    }
]

我想要得到的是该对象内的整个“子”数组

[
    {
        "_id": "6051cb588f974b3104715ec5",
        "parent": "6051cacf8f974b3104715ec4",
        "products": [],
        "isParent": true,
        "name": "Cameras",
        "description": "description",
        "createdAt": "2021-03-17T09:26:48.220Z",
        "updatedAt": "2021-03-17T09:29:35.608Z",
        "slug": "cameras",
        "__v": 0
    },
    {
        "_id": "6051cb5f8f974b3104715ec6",
        "parent": "6051cacf8f974b3104715ec4",
        "products": [
            "60515150d6ac5e08a4e796b4",
            "6051b8b0f8c80835480b28d3"
        ],
        "isParent": true,
        "name": "Computers",
        "description": "description",
        "createdAt": "2021-03-17T09:26:55.364Z",
        "updatedAt": "2021-03-20T20:42:50.779Z",
        "slug": "computers",
        "__v": 4
    },
    {
        "_id": "6051cb6f8f974b3104715ec7",
        "parent": "6051cacf8f974b3104715ec4",
        "products": [],
        "isParent": false,
        "name": "Car Electronics",
        "description": "description",
        "createdAt": "2021-03-17T09:27:11.108Z",
        "updatedAt": "2021-03-17T09:27:11.108Z",
        "slug": "car-electronics",
        "__v": 0
    },
    {
        "_id": "6051cb768f974b3104715ec8",
        "parent": "6051cacf8f974b3104715ec4",
        "products": [],
        "isParent": false,
        "name": "TV",
        "description": "description",
        "createdAt": "2021-03-17T09:27:18.422Z",
        "updatedAt": "2021-03-17T09:27:18.422Z",
        "slug": "tv",
        "__v": 0
    }
]

就像我提到的,这可以通过 const desiredResult = document[0].children; 完成,但我想在查询本身中执行此操作。

EDIT3:即使只有一个文档,聚合似乎总是会返回一组文档,我可以选择文档的外观,但是我不能只返回一个字段本身,而没有文档。这对我正在尝试做的事情来说很好 - 我可以将该文档(或它的特定字段)分配给一个变量。

【问题讨论】:

    标签: mongodb mongoose mongodb-query aggregation-framework


    【解决方案1】:

    使用https://mongoosejs.com/docs/populate.html

    MongoDB 在 >= 3.2 版本中具有类似连接的 $lookup 聚合运算符。 Mongoose 有一个更强大的替代方法,称为 populate(),它可以让您引用其他集合中的文档。

    填充是自动将文档中的指定路径替换为其他集合中的文档的过程。我们可以填充单个文档、多个文档、一个普通对象、多个普通对象或从查询返回的所有对象。让我们看一些例子。


    获取完整的数组

    { $project: { _id:0, children: 1 } }
    

    使用它来获取第一个元素

    从聚合项目管道中的数组中提取第一个元素

    { $project: { _id:0, children: { $arrayElemAt: [ "$children", 0 ] } } }
    
    
    if(document && document[0] && document[0].children) { // your logic }
    

    $arrayElemAt

    $project

    组合查询

    const document = await Category.aggregate([
      {
        $match: {
          slug: categorySlug,
        },
      },
      {
        $lookup: {
          from: 'categories',
          localField: '_id',
          foreignField: 'parent',
          as: 'children',
        },
      },
      { $project: { _id:0, children: { $arrayElemAt: [ "$children", 0 ] } } }
    ]);
    

    【讨论】:

    • 谢谢。学到了一些新东西,但不幸的是我想得到整个“儿童”数组。我更新了我的问题以包含所需结果的示例。
    • @Krzysztof 更新了答案。
    • 不是这样的。我可能还不清楚 - 我想要来自子数组的所有值,即数组本身。基本上只输出子数组。结果应该是一个包含“children”数组中所有对象的数组。如 EDIT#2 所示。我设法在查询之外得到了我想要的结果,但我想知道它是否可以在查询中完成。
    • @Krzysztof 聚合默认返回元素数组
    • @Krzysztof 你可以使用mongoosejs.com/docs/populate.html
    猜你喜欢
    • 1970-01-01
    • 2021-12-04
    • 1970-01-01
    • 2012-11-07
    • 2019-09-12
    • 2016-04-14
    • 1970-01-01
    • 2020-07-10
    • 1970-01-01
    相关资源
    最近更新 更多