首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在mangoose (物化路径类别)中获取类别的父项和子项的数组?

如何在mangoose (物化路径类别)中获取类别的父项和子项的数组?
EN

Stack Overflow用户
提问于 2021-05-03 20:50:26
回答 1查看 129关注 0票数 0

大家好,我想在nodejs应用程序中实现mongodb的物化路径类别层次结构,如果我有这两个文档,我想像树一样获得它们的数组,这一点我将会解释

集合:

代码语言:javascript
复制
const categoriesCollection = [
  {
    "_id": ObjectId("54fd7392742abeef6186a68e")
    , "name": "electronics"
    , "parent": "/"
    , "category": "/electronics"
  },


  {
    "_id": ObjectId("54fd7392742abeef6186a68e")
    , "name": "embedded"
    , "parent": "/electronics"
    , "category": "/electronics/embedded"
  },
  {
    "_id": ObjectId("54fd7392742abeef6186a68e")
    , "name": "controllers"
    , "parent": "/electronics"
    , "category": "/electronics/controllers"
  },

  {
    "_id": ObjectId("54fd7392742abeef6186a68e")
    , "name": "cases"
    , "parent": "/electronics"
    , "category": "/electronics/cases"
  },

  {
    "_id": ObjectId("54fd7392742abeef6186a68e")
    , "name": "big"
    , "parent": "/electronics/cases"
    , "category": "/electronics/cases/big"
  },
  {
    "_id": ObjectId("54fd7392742abeef6186a68e")
    , "name": "small"
    , "parent": "/electronics/cases"
    , "category": "/electronics/cases/small"
  },


]

const ProductsCollection = [
  {
    "_id": ObjectId("54fd7392742abeef6186a68e")
    , "name": "product1"
    , "cost": 125
    , "currency": "USD"
    , "categories": ["/electronics/embedded"]
  },
  {
    "_id": ObjectId("54fd7392742abeef6186a68e")
    , "name": "product2"
    , "cost": 134
    , "currency": "USD"
    , "categories": ["/electronics/controllers"]
  },
  {
    "_id": ObjectId("54fd7392742abeef6186a68e")
    , "name": "product3"
    , "cost": 133
    , "currency": "USD"
    , "categories": ["/electronics/cases/big"]
  },

  {
    "_id": ObjectId("54fd7392742abeef6186a68e")
    , "name": "product4"
    , "cost": 188
    , "currency": "USD"
    , "categories": ["/electronics/cases/small", "/electronics/cases"]
  },

]

我希望在树状结构中拥有类似于父项、子项和产品的输出数组:

代码语言:javascript
复制
const allCategories = [
  {

    name: "electronics",
    categories: [
      {
        name: "embedded",
        categories: [],
        products: [{ name: "product1" }]
      },
      {
        name: "controllers",
        categories: [],
        products: [{ name: "product2" }]
      },
      {
        name: "cases",
        categories: [
          {
            name: "big",
            categories: [],
            products: [{ name: "product3" }]
          },
          {
            name: "small",
            categories: [],
            products: [{ name: "product4" }]
          }
        ],
        products: [{ name: "product1" }]
      },

    ]

    ,
    products: [{ "name": "product4" }]

  }
]

我如何通过mongoose查询在这个数组中获得这个数组?

EN

回答 1

Stack Overflow用户

发布于 2021-05-03 22:53:45

在MongoDB中没有任何直接的方法来处理这种情况,您可以尝试$groupLookup和自定义逻辑,

只有深度的记录的

  • $match过滤器为/
  • $graphLookup,以获取categories数组中的子记录和深度数,并允许不删除具有products集合的空parent,并连接产品或categories
  • $addFields,以在products
  • $sort中仅选择depth level字段中的depth level字段,并在降序order
  • $group by parent字段中重建depthField categories数组categories

代码语言:javascript
复制
db.category.aggregate([
  { $match: { parent: "/" } },
  {
    $graphLookup: {
      from: "category",
      startWith: "$category",
      connectFromField: "category",
      connectToField: "parent",
      depthField: "level",
      as: "categories"
    }
  },
  {
    $unwind: {
      path: "$categories",
      preserveNullAndEmptyArrays: true
    }
  },
  {
    $lookup: {
      from: "products",
      localField: "categories.category",
      foreignField: "categories",
      as: "categories.products"
    }
  },
  {
    $addFields: {
      "categories.products": {
        $map: {
          input: "$categories.products",
          in: { name: "$$this.name" }
        }
      }
    }
  },
  { $sort: { "categories.level": -1 } },
  {
    $group: {
      _id: "$category",
      parent: { $first: "$parent" },
      name: { $first: "$name" },
      categories: { $push: "$categories" }
    }
  },

  • $addFields现在找到嵌套的级别类别并分配给它的级别,
    • $reduce to iterate categories
      • $addFields array.
      • initialize categories level默认值为-1,presentChild为[],对于用于初始化字段的条件,purpose
      • $let为[]:
        • prev as per condition如果两个level相等,则返回prevChild;否则,返回
          • prev as per condition如果两个prevChild相等,则返回presentChild;否则返回presentChild

代码语言:javascript
复制
- `in` to return `level` field and `prevChild` field from initialized fields 
    - `presentChild` `$filter` `categories` from `prev` array and return, merge current objects with `categories` array using `$mergeObjects` and concat with `current` array of let using `$concatArrays`

  • $addFields仅返回presentChild数组,因为我们只需要已处理的数组

代码语言:javascript
复制
  {
    $addFields: {
      categories: {
        $reduce: {
          input: "$categories",
          initialValue: { level: -1, presentChild: [], prevChild: [] },
          in: {
            $let: {
              vars: {
                prev: {
                  $cond: [
                    { $eq: ["$$value.level", "$$this.level"] },
                    "$$value.prevChild",
                    "$$value.presentChild"
                  ]
                },
                current: {
                  $cond: [{ $eq: ["$$value.level", "$$this.level"] }, "$$value.presentChild", []]
                }
              },
              in: {
                level: "$$this.level",
                prevChild: "$$prev",
                presentChild: {
                  $concatArrays: [
                    "$$current",
                    [
                      {
                        $mergeObjects: [
                          "$$this",
                          {
                            categories: {
                              $filter: {
                                input: "$$prev",
                                as: "e",
                                cond: { $eq: ["$$e.parent", "$$this.category"] }
                              }
                            }
                          }
                        ]
                      }
                    ]
                  ]
                }
              }
            }
          }
        }
      }
    }
  },
  { $addFields: { categories: "$categories.presentChild" } }
])

Playground

备注:这将导致海量数据的性能问题!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67369211

复制
相关文章

相似问题

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