命名戦略
underscored
オプション
Sequelizeはモデルにunderscored
オプションを提供します。true
の場合、このオプションはすべての属性のfield
オプションを、その名前のスネークケースバージョンに設定します。これは、アソシエーションによって自動的に生成される外部キーやその他の自動的に生成されるフィールドにも適用されます。例
const User = sequelize.define(
'user',
{ username: Sequelize.STRING },
{
underscored: true,
},
);
const Task = sequelize.define(
'task',
{ title: Sequelize.STRING },
{
underscored: true,
},
);
User.hasMany(Task);
Task.belongsTo(User);
上記では、UserモデルとTaskモデルの両方がunderscored
オプションを使用しています。また、それらの間に一対多のリレーションシップがあります。また、timestamps
はデフォルトでtrueであるため、createdAt
およびupdatedAt
フィールドも自動的に作成されるはずです。
underscored
オプションがない場合、Sequelizeは自動的に次のように定義します。
- 各モデルの
createdAt
属性。各テーブルのcreatedAt
という名前の列を指します。 - 各モデルの
updatedAt
属性。各テーブルのupdatedAt
という名前の列を指します。 Task
モデルのuserId
属性。taskテーブルのuserId
という名前の列を指します。
underscored
オプションが有効になっている場合、Sequelizeは代わりに次のように定義します。
- 各モデルの
createdAt
属性。各テーブルのcreated_at
という名前の列を指します。 - 各モデルの
updatedAt
属性。各テーブルのupdated_at
という名前の列を指します。 Task
モデルのuserId
属性。taskテーブルのuser_id
という名前の列を指します。
どちらの場合も、フィールドはJavaScript側ではキャメルケースであることに注意してください。このオプションは、これらのフィールドがデータベース自体にどのようにマッピングされるかのみを変更します。すべての属性のfield
オプションは、スネークケースバージョンに設定されますが、属性自体はキャメルケースのままです。
このように、上記のコードでsync()
を呼び出すと、次のものが生成されます。
CREATE TABLE IF NOT EXISTS "users" (
"id" SERIAL,
"username" VARCHAR(255),
"created_at" TIMESTAMP WITH TIME ZONE NOT NULL,
"updated_at" TIMESTAMP WITH TIME ZONE NOT NULL,
PRIMARY KEY ("id")
);
CREATE TABLE IF NOT EXISTS "tasks" (
"id" SERIAL,
"title" VARCHAR(255),
"created_at" TIMESTAMP WITH TIME ZONE NOT NULL,
"updated_at" TIMESTAMP WITH TIME ZONE NOT NULL,
"user_id" INTEGER REFERENCES "users" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
PRIMARY KEY ("id")
);
単数形と複数形
一見すると、Sequelizeで名前の単数形と複数形のどちらを使用する必要があるかについて混乱する可能性があります。このセクションでは、それを少し明確にすることを目的としています。
Sequelizeは、内部でinflectionというライブラリを使用しているため、不規則な複数形(person -> people
など)が正しく計算されることに注意してください。ただし、別の言語で作業している場合は、名前の単数形と複数形を直接定義することもできます。sequelizeを使用すると、いくつかのオプションを使用してこれを行うことができます。
モデルを定義する場合
モデルは単数形で定義する必要があります。例
sequelize.define('foo', { name: DataTypes.STRING });
上記では、モデル名はfoo
(単数形)であり、それぞれのテーブル名はfoos
です。Sequelizeはテーブル名の複数形を自動的に取得するためです。
モデルで参照キーを定義する場合
sequelize.define('foo', {
name: DataTypes.STRING,
barId: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'bars',
key: 'id',
},
onDelete: 'CASCADE',
},
});
上記の例では、別のモデルを参照するキーを手動で定義しています。これを行うことは通常ではありませんが、行う必要がある場合は、そこにテーブル名を使用する必要があります。これは、参照が参照されたテーブル名で作成されるためです。上記の例では、複数形(bars
)が使用されています。これは、bar
モデルがデフォルト設定で作成された(基礎となるテーブルを自動的に複数形にする)ことを前提としています。
遅延ロードからデータを取得する場合
クエリでinclude
を実行すると、含まれるデータは、次のルールに従って、返されるオブジェクトの追加フィールドに追加されます。
- 単一のアソシエーション(
hasOne
またはbelongsTo
)から何かを含める場合-フィールド名はモデル名の単数形になります。 - 複数のアソシエーション(
hasMany
またはbelongsToMany
)から何かを含める場合-フィールド名はモデルの複数形になります。
要するに、フィールドの名前は、各状況で最も論理的な形式を取ります。
例
// Assuming Foo.hasMany(Bar)
const foo = Foo.findOne({ include: Bar });
// foo.bars will be an array
// foo.bar will not exist since it doens't make sense
// Assuming Foo.hasOne(Bar)
const foo = Foo.findOne({ include: Bar });
// foo.bar will be an object (possibly null if there is no associated model)
// foo.bars will not exist since it doens't make sense
// And so on.
エイリアスを定義するときに単数形と複数形をオーバーライドする
アソシエーションのエイリアスを定義するときは、単に{ as: 'myAlias' }
を使用する代わりに、単数形と複数形を指定するオブジェクトを渡すことができます。
Project.belongsToMany(User, {
as: {
singular: 'líder',
plural: 'líderes',
},
});
モデルがアソシエーションで常に同じエイリアスを使用することがわかっている場合は、単数形と複数形をモデル自体に直接提供できます。
const User = sequelize.define(
'user',
{
/* ... */
},
{
name: {
singular: 'líder',
plural: 'líderes',
},
},
);
Project.belongsToMany(User);
ユーザーインスタンスに追加されたmixinは、正しい形式を使用します。たとえば、project.addUser()
の代わりに、Sequelizeはproject.getLíder()
を提供します。また、project.setUsers()
の代わりに、Sequelizeはproject.setLíderes()
を提供します。
注:as
を使用してアソシエーションの名前を変更すると、外部キーの名前も変更されることに注意してください。したがって、この場合は、関係する外部キーも直接指定することをお勧めします。
// Example of possible mistake
Invoice.belongsTo(Subscription, { as: 'TheSubscription' });
Subscription.hasMany(Invoice);
上記の最初の呼び出しでは、Invoice
にtheSubscriptionId
という外部キーが設定されます。ただし、2番目の呼び出しでは、Invoice
にも外部キーが設定されます(ご存知のとおり、hasMany
呼び出しではターゲットモデルに外部キーが配置されるため)。ただし、名前はsubscriptionId
になります。このようにして、subscriptionId
列とtheSubscriptionId
列の両方ができます。
最善の方法は、外部キーの名前を選択し、両方の呼び出しに明示的に配置することです。たとえば、subscription_id
が選択された場合
// Fixed example
Invoice.belongsTo(Subscription, {
as: 'TheSubscription',
foreignKey: 'subscription_id',
});
Subscription.hasMany(Invoice, { foreignKey: 'subscription_id' });