【问题标题】:Recursive include Sequelize?递归包括Sequelize?
【发布时间】:2016-03-12 04:08:58
【问题描述】:

我的类别可以有子类别

当我在做 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);
        })
});

结果只给我带来了一层嵌套包含。

[  
   {  
      dataValues:{  

      },
      subcategory:{  
         model:{  
            dataValues:{  

            }
            // no subcategory here            
         }
      }
   }
]

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

【问题讨论】:

    标签: javascript mysql orm sequelize.js


    【解决方案1】:

    Sequelize 目前不支持公用表表达式和递归 CTE。添加在 find* 系列方法中包含 CTE 的功能将允许 find* 执行递归查询。

    这里是示例的链接。

    Common Table Expressions and Recursive Queries

    【讨论】:

      【解决方案2】:

      这是 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;
      };
      
      

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

      【讨论】:

        【解决方案3】:

        假设您有 5 个不同的模型 A、B、C、D、E 并且 A 与 B 相关联,B 与 C 相关联,依此类推。 因此,在为 A 获取数据时,您可以使用

        获取所有嵌套的子类别层次结构

        include: [{ all: true, nested: true }]

        示例: A.findAll(where:{// add conditions}, { include: [{ all: true, nested: true }]});

        【讨论】:

        • 他要求的不是针对不同模型的解决方案,而是要嵌套相同的模型。
        【解决方案4】:

        有一个节点模块可以处理它:sequelize-hierarchy
        它将列 parentIdhierarchyLevel 添加到您的表中。 例如,这就是我在树中排序员工技能的操作。
        技能可以是“Macro”->“Excel”->“Office”->“计算机
        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
        });
        

        【讨论】:

          【解决方案5】:

          如果找到解决方案很少 第一个更复杂,但性能更好:

          这个是关于在 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);
                      }
                  });
              });
          };
          

          所以它会遍历类别并递归地扩展它们。

          也许这也会对某人有所帮助。

          【讨论】:

            猜你喜欢
            • 2023-03-17
            • 2015-07-27
            • 2015-02-03
            • 1970-01-01
            • 1970-01-01
            • 2017-10-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多