gpt4 book ai didi

node.js - 如何在 MongoDB 请求中获取 parent 和 parent 的 sibling

转载 作者:行者123 更新时间:2023-12-03 12:12:51 27 4
gpt4 key购买 nike

在 MongoDB/NodeJS 项目中,我已经对集合的元素进行了排序,就像家谱一样。在特定 route ,我试图获取元素的父元素,以及父元素的兄弟元素,具有给定的深度,如下图所示:

Collection tree, items wanted through the request

在集合中,对于每个项目,我存储其他数据:

  • parentId
  • 祖父 ID
  • isRoot( bool 值)

  • 我试图用 GraphLookup 做一些事情,基于我的链接请求 parentIdgrandParentId , 像这样 :
    db.arguments.aggregate([
    {$match: { _id: mongoose.Types.ObjectId(id) }},
    ,
    {$graphLookup: {
    from: 'arguments',
    startWith: '$grandParentId',
    connectFromField: 'grandParentId',
    connectToField: 'parentId',
    maxDepth: Number(parentsDepth),
    as: 'parentsHierarchy',
    depthField: 'depth',
    restrictSearchWithMatch: { isDeleted: false }
    }}
    ])

    它工作得很好,但问题是它无法检索没有 parentId 的根元素。 .
    我想过做两个单独的 View ,每个 View 都包含一个 GraphLookup (一个基于 parentId/ grandParentId ,另一个基于 id/ parentId ),然后在删除重复项的同时合并两个 View ,但是为了只获取根元素而执行两个潜在的大请求看起来很奇怪.

    我想找到一个可靠的解决方案,因为我计划允许一个项目有多个父项。

    最佳答案

    您可以将其更改为多个步骤:

  • 查找直系祖先( parent 、祖 parent 等)的数组
  • 查找每个祖 parent 和“更高”的直系后代(从而为您提供 parent sibling 、祖 parent sibling 等)
  • 将两个数组合并为一个集合(从而确保唯一性)
  • db.arguments.aggregate([
    {$match: { _id: mongoose.Types.ObjectId(id) }},
    {$graphLookup: {
    from: 'arguments',
    startWith: '$parentId',
    connectFromField: 'parentId',
    connectToField: '_id',
    maxDepth: Number(parentsDepth),
    as: 'parentsHierarchy',
    depthField: 'depth',
    restrictSearchWithMatch: { isDeleted: false }
    }},
    {$unwind: "$parentsHierarchy"},
    {$lookup: {
    from: 'arguments',
    let: { id: '$parentsHierarchy._id', depth: '$parentsHierarchy.depth' },
    pipeline: [
    {$match:{$expr:{
    $and: [{
    $eq: ['$$id', '$parentId']
    },{
    $gte: ["$$depth", 2]
    }]
    }}},
    {$addFields:{
    depth: {$sum: ["$$depth", -1]}
    }}],
    as: 'children'
    }},
    {$group:{
    _id: "$_id",
    parentsHierarchy: {$addToSet: "$parentsHierarchy"},
    children: {$push: "$children"}
    // The rest of your root fields will have to be added here (someField: {$first: "$someField"})
    }},
    {$addFields:{
    hierarchy: {$setUnion: ["$children", "$parentsHierarchy"]}
    }}
    ])

    How to push multiple columns' value within group关于 $setUnion .

    原答案:

    如果你只对 parent 和 parent 的 sibling 感兴趣,你可以使用 $lookup舞台代替 $graphLookup ,因为您不需要图形给您的递归。

    您的 $lookup可以这样做:
    db.test.aggregate([
    {$lookup: {
    from: 'arguments',
    let: { parentId: '$parentId', grandParentId: '$grandParentId' },
    pipeline: [{$match:{$expr:{
    $or: [{
    $eq: ['$_id', '$$parentId']
    },{
    $eq: [{$ifNull: ['$parentId', 'xyz']}, '$$grandParentId']
    }]
    }}}],
    as: 'parentsAndTheirSiblings'
    }}
    ])

    这样你的根元素应该仍然可以被 $match 的第一部分找到。在 pipeline .

    请注意,我正在使用 $ifNull在第二部分过滤掉“根”元素,因为 $parentId$$grandparentId在查找深度为 1 的元素时,将为 null 或未定义。如果预期行为是应该为任何深度为 1 的元素找到所有根元素(如果根元素被视为兄弟元素),那么您可以摆脱它并简单地进行比较 $parentId$$grandparentId直截了当。

    查找文档: https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/

    关于node.js - 如何在 MongoDB 请求中获取 parent 和 parent 的 sibling ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61009278/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com