web-dev-qa-db-ja.com

続編で多対多の関連付けを実装する方法

私は2つのテーブルを持っています:本と記事の間には多対多の関係があります。参加テーブルはBookArticlesです。

models/books.js

module.exports = function(sequelize, DataTypes) {
  return Food = sequelize.define("Book", {
    id: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      allowNull: false,
      autoIncrement: true,
      unique: true
    }
  });
}

models/articles.js

module.exports = function(sequelize, DataTypes) {
  return Food = sequelize.define("Article", {
    id: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      allowNull: false,
      autoIncrement: true,
      unique: true
    }
  });
}

models/bookArticles.js

module.exports = function(sequelize, DataTypes) {
  return Food = sequelize.define("BookArticles", {
    id: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      allowNull: false,
      autoIncrement: true,
      unique: true
    },
   bookId: {
      type: DataTypes.INTEGER,
      references: 'Book',
      referencesKey: 'id',
      allowNull: false
    },
    ArticleId: {
      type: DataTypes.INTEGER,
      references: 'Article',
      referencesKey: 'id',
      allowNull: false
    },
  });
}

そして、models/index.js

m.BookArticles.belongsTo(m.Book);
m.Book.hasMany(m.Article, {through: m.BookArticles});


m.BookArticles.belongsTo(m.Article);
m.Article.hasMany(m.Books, {through: m.BookArticles});

しかし、本の記事を入手できませんでした

どうすれば入手できますか?

35
Anuj

_Update 17 Feb 15_:1.新しいv2は、N:Mに2x .belongsToMany()を使用します。

これらすべての関連を理解することには多くの問題がありました。

一般的に、作成されるテーブルとアソシエーションによって得られるメソッドについて混乱していると思います。

以下のテキストは、チームがこれらすべてを処理する方法を標準化するために書いたものです。命名規則に関しては、単にSequelizeにすべてをデフォルトにした場合、それを無視できます。

ただし、多くの理由により、明示的に規則に名前を付けることをお勧めします。

簡単な説明:

O:O、Parent.hasOne(Child) AND Child.belongsTo(Parent)を設定します。

O:M、Parent.hasMany(Child) AND Child.belongsTo(Parent)をセットアップします。

N:M *、Parent.belongsToMany(Child, {through: 'Parent_Child', foreignKey: 'Parent_rowId'})およびChild.belongsToMany(Parent, {through: 'Parent_Child', foreignKey: 'Child_rowId'})をセットアップします。

HasOne()、hasMany()、belongsTo()/ belongsToMany()によって得られるメソッド

上記の関連付けを行う理由を理解するために、各モデルで得られる方法を知ることから始めます。

hasOne():

Parent.hasOne(Child)を設定する際、parent DAOインスタンスで利用可能なメソッド:

_parent.getChild,
parent.setChild,
parent.addChild,
parent.createChild,
parent.removeChild,
parent.hasChild
_

多くを持っています():

Parent.hasMany(Child)を設定する際、parent DAOインスタンスで利用可能なメソッド:

_parent.getChildren,
parent.setChildren,
parent.addChild,
parent.createChild,
parent.removeChild,
parent.hasChild,
parent.hasChildren
_

belongsTo()/ belongsToMany:

Child.belongsTo(Parent)を設定する際、child DAOインスタンスで利用可能なメソッド:

_child.getParent,
child.setParent,
child.createParent

//belongsToMany
child.getParents,
child.setParents,
child.createParents
_

関係を設定するための構文。そして私たちの慣習

O:OおよびO:Mの場合:

_Parent.hasOne(Child, {foreignKey: 'Parent_childID'});
Child.belongsTo(Parent, {foreignKey: 'Parent_childID'});
_

ForeignKeysをParent_childIDとして明示的に定義したことに注意してください。これは、TableName_keyName規則にこのPascalCase_camelCaseが必要だからです。

多対多の関係

N:M関係の場合、これを行います。

_Parent.belongsToMany( Child, {
    as: [Relationship],
    through: [Parent_Child] //this can be string or a model,
    foreignKey: 'Parent_rowId'
});

Child.belongsToMany(Parent, {
    as: [Relationship2],
    through: [Parent_Child],
    foreignKey: 'Child_rowId'
});
_

_*New in v2_:「スルー」の使用は必須です。標準として、「through」パラメーターを使用して、一貫性を保ち、落とし穴を減らすために、すべてのクロステーブル名を明示的に定義します。

上記は、RelationshipIdおよびRelationship2IDを使用してParent_Childを作成します。

SequelizeはforeignKeyを自動的に作成できますが、通常は独自に定義します。

テーブルとキーの命名規則

テーブル名:PascalCase

キー:camelCase

foreignkeys:TableNameInPascalCase_foreignKeyInCamelCase

例:User_pictureId意味:pictureIdのこのキーは、Userテーブルから取得されました。

181
Calvintwr

bookArticlesモデルを削除し、関係を更新します。

m.Book.hasMany(m.Article, {through: 'book_articles'});
m.Article.hasMany(m.Books, {through: 'book_articles'});
14
ahiipsa

これは私が2つのモデルユーザーモデルを持っていた同様の問題を解決した方法です

var user = sequelize.define('user', {
    name: {
        Sequelize.STRING(255)
    },
    email: {
        type: Sequelize.STRING(255),
        unique: true,
        validate: {
            isEmail: true
        }
    }
});

およびロールモデル

var Role = sequelize.define('role', {
    name: {
        Sequelize.ENUM('ER', 'ALL', 'DL')
    },
    description: {
        type: Sequelize.TEXT
    }
});

次に、ユニオンモデルUserRoleを作成しました

var UserRole = sequelize.define('user_role', {
    id: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        autoIncrement: true
    },
    name: {
        type: Sequelize.ENUM('Admin', 'Staff', 'Customer', 'Owner')
    }
});

注:UserRoleのIDを明示的に定義する必要があります。そうしないと、sequelizeはこの場合2つの外部キーを使用しますuser_idおよびrole_idを主キーとして。

次に、次のように多くの関係に属するを作成しました

User.belongsToMany(Role, { as: 'Roles', through: { model: UserRole, unique: false }, foreignKey: 'user_id' });
Role.belongsToMany(User, { as: 'Users', through: { model: UserRole, unique: false }, foreignKey: 'role_id' });
6
Buhiire Keneth

M:Mテーブルを介した関係BookArticles

m.Book.belongsToMany(m.Article, {through: m.BookArticles});
m.Article.belongsToMany(m.Books, {through: m.BookArticles});
3