【问题标题】:"has many through" association in SequelizeSequelize 中的 "has many through" 关联
【发布时间】:2017-07-31 05:35:44
【问题描述】:

假设我们有三个模型:

  • 书籍
  • 章节
  • 段落

这是他们的关联:

  • 书籍有很多章节
  • 章节有很多段落
  • 书籍有许多段落,通过章节

是否可以与 Sequelize 定义“有很多,通过”关系?如果有,怎么做?

以下是书籍、章节和段落的基本模型:

// Book model
const Book = sequelize.define('Book', {
  id: {
    type: DataTypes.INTEGER,
    allowNull: false,
    primaryKey: true
  },
  title: {
    type: DataTypes.STRING
  }
}, {
  classMethods: {
    associate: (models) => {
      Book.hasMany(models.Chapter, {
        foreignKey: 'bookId',
        as: 'chapters'
      });
    }
    // How can you add an association for a book having many paragraphs, through chapters?
  }
});


// Chapter model
const Chapter = sequelize.define('Chapter', {
  id: {
    type: DataTypes.INTEGER,
    allowNull: false,
    primaryKey: true
  },
  title: {
    type: DataTypes.STRING
  }
}, {
  classMethods: {
    associate: (models) => {
      Chapter.hasMany(models.Paragraph, {
        foreignKey: 'chapterId',
        as: 'paragraphs'
      });

      Chapter.belongsTo(models.Book, {
        foreignKey: 'bookId'
      });
    }
  }
});


// Paragraph Model
const Paragraph = sequelize.define('Paragraph', {
  id: {
    type: DataTypes.INTEGER,
    allowNull: false,
    primaryKey: true
  },
  content: {
    type: DataTypes.TEXT
  }
}, {
  classMethods: {
    associate: (models) => {
      Paragraph.belongsTo(models.Chapter, {
        foreignKey: 'chapterId'
      });
    }
    // How can you add an association for paragraphs belonging to a book "through" chapters?
  }
});

【问题讨论】:

    标签: sequelize.js


    【解决方案1】:

    不幸的是,没有这种可能性。您可以做的是在BookParagraph 模型上创建一些instanceMethods,例如getParagraphsgetBook,以便检索相关元素

    // in Book model
    instanceMethods: {
        getParagraphs: function(options){
            options.include = [
                {
                    model: sequelize.models.Chapter,
                    attributes: [],
                    where: {
                        bookId: this.get('id')
                    }
                }
            ];
    
            return sequelize.models.Paragraph.findAll(options);
        }
    }
    

    上述方法将返回其章节属于指定书籍的所有段落。您可以在 Paragraph 模型中对 getBook 执行相反的操作。

    另一方面,为了检索包含所有章节及其段落的书,您只需执行 findAll 嵌套 include(开玩笑地提醒一下)。

    【讨论】: