大家好,我想在nodejs应用程序中实现mongodb的物化路径类别层次结构,如果我有这两个文档,我想像树一样获得它们的数组,这一点我将会解释
集合:
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"]
},
]我希望在树状结构中拥有类似于父项、子项和产品的输出数组:
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查询在这个数组中获得这个数组?
发布于 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 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现在找到嵌套的级别类别并分配给它的级别,categories $addFields array.categories level默认值为-1,presentChild为[],对于用于初始化字段的条件,purpose$let为[]:prev as per condition如果两个level相等,则返回prevChild;否则,返回prev as per condition如果两个prevChild相等,则返回presentChild;否则返回presentChild- `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数组,因为我们只需要已处理的数组 {
$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" } }
])备注:这将导致海量数据的性能问题!
https://stackoverflow.com/questions/67369211
复制相似问题