javascript 递归包括Sequelize?

1sbrub3j  于 2023-04-04  发布在  Java
关注(0)|答案(6)|浏览(319)

我有一个可以有子类别的类别
当我做findAll的时候,我想包括所有嵌套的,但我不知道深度。

var includeCondition = { 
                         include: [
                            { 
                               model: models.categories,
                               as:'subcategory', nested: true 
                            }]
                       };

models.categories.findAll(includeCondition)
        .then(function (categories) {
            resolve(categories);
        })
        .catch(function (err) {
            reject(err);
        })
});

结果只显示一个嵌套的include级别。

[  
   {  
      dataValues:{  

      },
      subcategory:{  
         model:{  
            dataValues:{  

            }
            // no subcategory here            
         }
      }
   }
]

我能以某种方式使sequalize包含那些嵌套的子类别吗?

yebdmbv4

yebdmbv41#

有几个解决方案,如果发现这个第一个更复杂,但将给予更好的性能:
这是关于在MySQL中实现分层数据结构的,我喜欢这里的指南
http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
这个模型叫做嵌套集合模型。
我自己实现的第二个解决方案是递归扩展,这个解决方案使用了大量的mysql请求,我相信可以改进,但它是一个快速的解决方案,效果很好。

var expandSubcategories = function (category) {
    return new promise(function (resolve, reject) {
        category.getSubcategories().then(function (subcategories) {
            //if has subcategories expand recursively inner subcategories
            if (subcategories && subcategories.length > 0) {
                var expandPromises = [];
                _.each(subcategories, function (subcategory) {
                    expandPromises.push(expandSubcategories(subcategory));
                });

                promise.all(expandPromises).then(function (expandedCategories) {
                    category.subcategories = [];

                    _.each(expandedCategories, function (expandedCategory) {
                        category.subcategories.push(expandedCategory);
                    }, this);

                    //return self with expanded inner
                    resolve(category);
                });

            } else {
                //if has no subcategories return self
                resolve(category);
            }
        });
    });
};

所以它遍历类别并递归地扩展它们。
也许这也能帮助到别人。

t98cgbkg

t98cgbkg2#

这是ihoryam在ES6上的答案,使用async/await,箭头函数() =>和Sequelize ORM来获取数据,而不是使用Lodash。

const getSubCategoriesRecursive = async (category) => {
  let subCategories = await models.category.findAll({
      where: {
          parentId: category.id
      },
      raw : true
  });

  if (subCategories.length > 0) {
      const promises = [];
      subCategories.forEach(category => {
          promises.push(getSubCategoriesRecursive(category));
      });
      category['subCategories'] = await Promise.all(promises);
  }
  else category['subCategories'] = []; 
  return category;
};

异步函数返回promise,不需要精确的return new promise(...)

w46czmvw

w46czmvw3#

有一个节点模块来处理它:sequelize-hierarchy
它将列 parentIdhierarchyLevel 添加到您的表中。作为一个示例,这是我在树中对员工技能进行排序时所做的。
技能可以是“Macro”-〉“Excel”-〉“Office”-〉“Computer
database.js:

const  Sequelize = require('sequelize');
require('sequelize-hierarchy')(Sequelize);
const sequelize = new Sequelize("stackoverflow", null, null, {
  dialect: "sqlite",
  storage: "database.db"
});
sequelize.sync().then(() => {console.log("Database ready");});
module.exports = sequelize;

skill.js:

module.exports = (sequelize, DataTypes) => {
  const Skill = sequelize.define("skill", {
    name:           DataTypes.STRING,
  });
  Skill.isHierarchy();
  return Skill;
};

然后在您的控制器中:

Skill.findAll().then(skills => {
  res.send(skills); // Return a list
});
Skill.findAll({ hierarchy: true }).then(skills => {
  res.send(skills); // Return a tree
});
b0zn9rqh

b0zn9rqh4#

Sequelize目前不支持通用表表达式和递归CTE。如果在find* 方法家族中添加包含CTE的功能,则find* 将可以执行递归查询。
这里是例子的链接。
Common Table Expressions and Recursive Queries

f1tvaqid

f1tvaqid5#

sequelize-hierarchy与Sequelize v6不兼容。这是我在尝试Etienne Duverney代码后从ChatGPT得到的:

const getChildrenRecursive = async (menu) => {
  const childrenMenus = await models.Menu.findAll(
    { where: { parentId: menu.id }, raw: true },
  );
  const children = await Promise.all(childrenMenus.map(async (child) => {
    const childObj = {
      ...child,
      children: await getChildrenRecursive(child),
    };
    return childObj;
  }));
  return children;
};

这将给予你所有给定id的后代。如果没有孩子,值将是空数组[]。

sxpgvts3

sxpgvts36#

假设你有5个不同的模型A、B、C、D、E,A与B相关联,B与C相关联,以此类推。
include: [{ all: true, nested: true }]
示例:A.findAll(where:{// add conditions}, { include: [{ all: true, nested: true }]});

相关问题