我正在尝试创建一个函数,该函数可以将nested set model对象数组转换为对象数组内的普通嵌套对象数组。
当前,我对深度限制为2的临时解决方案不满意。基本上,它是使用某些Knex的服务器端控制器:
const getCategories = (res, db) => {
db.raw(`
SELECT child.id, child.name, child.path
FROM product_category parent
JOIN product_category child
ON child.lower BETWEEN parent.lower AND parent.upper
WHERE parent.id = 1
AND
(
SELECT COUNT(*)
FROM product_category node
WHERE child.lower BETWEEN node.lower AND node.upper
AND node.lower BETWEEN parent.lower AND parent.upper
) = 2
ORDER BY child.id
`)
.then(categories => {
if (categories.rows.length) {
const categoryPromises = categories.rows.map(category => {
return db.raw(`
SELECT child.id, child.name, child.path
FROM product_category parent
JOIN product_category child
ON child.lower BETWEEN parent.lower AND parent.upper
WHERE parent.id = ${category.id}
AND
(
SELECT COUNT(*)
FROM product_category node
WHERE child.lower BETWEEN node.lower AND node.upper
AND node.lower BETWEEN parent.lower AND parent.upper
) = 2
`)
.then(subcategories => {
return { ...category, subcategories: subcategories.rows }
})
})
return Promise.all(categoryPromises)
.then(products => {
res.json(products)
})
} else {
res.status(400).json("No categories")
}
})
}
模式在这里:http://sqlfiddle.com/#!17/a20af
嵌套集模型是一种处理层次结构数据的方法,该方法将子节点封闭在边界中(通常称为lft
和rgt
)。因此,如果lft
的{{1}}和rgt
值介于node1
的{{1}}和lft
值之间,则表示{{1} }是rgt
的子代(我希望这可以解决)。
例如,我有以下数组:
node2
我希望它具有类似这样的输出(如果有多个根节点,则为数组):
node1
答案 0 :(得分:1)
我写了这个递归解决方案。希望能有所帮助。如果您有任何疑问,请问我。 我只是检查一个元素是否在另一个元素的right和left属性内。在这种情况下,我将其添加到他的父亲(和每个主持人)中。我重复相同的操作,直到没有“父亲”为止。
const categories = [
{
id: 1,
name: "Products",
lft: 1,
rgt: 22
},
{
id: 2,
name: "Boats",
lft: 2,
rgt: 15
},
{
id: 3,
name: "Rescue Boats",
lft: 3,
rgt: 4
},
{
id: 4,
name: "Dive Boats",
lft: 5,
rgt: 6
},
{
id: 5,
name: "Tamarans",
lft: 7,
rgt: 8
},
{
id: 6,
name: "Dragon Boats",
lft: 9,
rgt: 10
},
{
id: 7,
name: "Kayaks",
lft: 11,
rgt: 12
},
{
id: 8,
name: "Speedboats",
lft: 13,
rgt: 14
},
{
id: 9,
name: "Other Products",
lft: 16,
rgt: 21
},
{
id: 10,
name: "Slides",
lft: 17,
rgt: 18
},
{
id: 11,
name: "Buoys",
lft: 19,
rgt: 20
}
]
function create_tree(array){
if(array.every(x => array.every(y => !(y.lft > x.lft && y.rgt < x.rgt))))
return array.map(x => {return{id:x.id, name:x.name, subcategories: x.subcategories}});
else
return create_tree(array.map(x => {return {
id: x.id,
name: x.name,
lft: x.lft,
rgt: x.rgt,
subcategories: array.filter(y => y.lft > x.lft && y.rgt < x.rgt).map(t => {return (t.subcategories) ? {id: t.id, name: t.name, subcategories: t.subcategories} : {id: t.id, name: t.name}})
}}).filter(t => t.subcategories && t.subcategories.length > 0));
}
console.log(create_tree(categories));