如何使用 Sequelize 创建嵌套对象和关系
How to use Sequelize create with nested objects and relations
我有 3 个模型。用户、项目和位置。
User.hasMany(Item)
Location.hasMany(Item)
Item.belongsTo(User)
Item.belongsTo(Location)
这会运行,但不会在位置 table 中创建位置外键或位置行。
models.User.create(
{
username: 'ddavids',
email: 'hello@david.com',
password: '12345678',
items: [
{
itemName: 'Good Book',
orderDate: '2020-01-20',
locations: { locationName: 'floor' }
},
{
itemName: 'Bad Book',
orderDate: '2020-01-21',
locations: { locationName: 'shelf' }
}
]
},
{
include: [{ model: models.Item, include: [models.Location] }]
}
)
这会正确创建项目和位置,但显然不是在用户下。
models.Location.create(
{
locationName: 'floor',
items: [
{
itemName: 'Good Book',
orderDate: '2020-01-20',
locations: { locationName: 'floor' }
},
{
itemName: 'Bad Book',
orderDate: '2020-01-21',
locations: { locationName: 'shelf' }
}
]
},
{ include: [models.Item] }
)
我想不通的是,我的关系是否采用了错误的方式来解决这个问题,或者它是否存在创建限制,我应该继续前进还是什么。
我的最终目标将是类似的东西。
User.hasMany(Order)
Order.belongsTo(User)
Order.hasMany(Item)
Item.belongsTo(Order)
Location.hasMany(Item)
Item.belongsTo(location)
Supplier.hasMany(Item)
Item.belongsTo(Supplier)
我目前使用 create 只是为了在我进行更改时创建一些假数据。因此,如果有更好的方式为数据库播种,那将是我的最终目标。
因为Location
和Item
模型的关联是一对多的。所以你应该改变
locations: { locationName: 'floor' }
到 location: { locationName: 'floor' }
。 Item
的位置不应该是复数。这意味着每个项目都属于一个位置。
这是工作示例:
index.ts
:
import { sequelize } from '../../db';
import { Model, DataTypes } from 'sequelize';
class User extends Model {}
User.init(
{
username: DataTypes.STRING,
email: DataTypes.STRING,
password: DataTypes.STRING,
},
{ sequelize, modelName: 'user' },
);
class Location extends Model {}
Location.init(
{
locationName: DataTypes.STRING,
},
{ sequelize, modelName: 'location' },
);
class Item extends Model {}
Item.init(
{
itemName: DataTypes.STRING,
orderDate: DataTypes.STRING,
},
{ sequelize, modelName: 'item' },
);
User.hasMany(Item);
Location.hasMany(Item);
Item.belongsTo(User);
Item.belongsTo(Location);
(async function test() {
try {
await sequelize.sync({ force: true });
await User.create(
{
username: 'ddavids',
email: 'hello@david.com',
password: '12345678',
items: [
{
itemName: 'Good Book',
orderDate: '2020-01-20',
location: { locationName: 'floor' },
},
{
itemName: 'Bad Book',
orderDate: '2020-01-21',
location: { locationName: 'shelf' },
},
],
},
{
include: [{ model: Item, include: [Location] }],
},
);
} catch (error) {
console.log(error);
} finally {
await sequelize.close();
}
})();
执行以上代码后,查看数据库中的数据记录:
node-sequelize-examples=# select * from "user";
id | username | email | password
----+----------+-----------------+----------
1 | ddavids | hello@david.com | 12345678
(1 row)
node-sequelize-examples=# select * from "location";
id | locationName
----+--------------
1 | floor
2 | shelf
(2 rows)
node-sequelize-examples=# select * from "item";
id | itemName | orderDate | userId | locationId
----+-----------+------------+--------+------------
1 | Good Book | 2020-01-20 | 1 | 1
2 | Bad Book | 2020-01-21 | 1 | 2
(2 rows)
按预期插入数据记录。
续集版本:"sequelize": "^5.21.3",
源代码:https://github.com/mrdulin/node-sequelize-examples/tree/master/src/examples/Whosebug/59937776
我有 3 个模型。用户、项目和位置。
User.hasMany(Item)
Location.hasMany(Item)
Item.belongsTo(User)
Item.belongsTo(Location)
这会运行,但不会在位置 table 中创建位置外键或位置行。
models.User.create(
{
username: 'ddavids',
email: 'hello@david.com',
password: '12345678',
items: [
{
itemName: 'Good Book',
orderDate: '2020-01-20',
locations: { locationName: 'floor' }
},
{
itemName: 'Bad Book',
orderDate: '2020-01-21',
locations: { locationName: 'shelf' }
}
]
},
{
include: [{ model: models.Item, include: [models.Location] }]
}
)
这会正确创建项目和位置,但显然不是在用户下。
models.Location.create(
{
locationName: 'floor',
items: [
{
itemName: 'Good Book',
orderDate: '2020-01-20',
locations: { locationName: 'floor' }
},
{
itemName: 'Bad Book',
orderDate: '2020-01-21',
locations: { locationName: 'shelf' }
}
]
},
{ include: [models.Item] }
)
我想不通的是,我的关系是否采用了错误的方式来解决这个问题,或者它是否存在创建限制,我应该继续前进还是什么。 我的最终目标将是类似的东西。
User.hasMany(Order)
Order.belongsTo(User)
Order.hasMany(Item)
Item.belongsTo(Order)
Location.hasMany(Item)
Item.belongsTo(location)
Supplier.hasMany(Item)
Item.belongsTo(Supplier)
我目前使用 create 只是为了在我进行更改时创建一些假数据。因此,如果有更好的方式为数据库播种,那将是我的最终目标。
因为Location
和Item
模型的关联是一对多的。所以你应该改变
locations: { locationName: 'floor' }
到 location: { locationName: 'floor' }
。 Item
的位置不应该是复数。这意味着每个项目都属于一个位置。
这是工作示例:
index.ts
:
import { sequelize } from '../../db';
import { Model, DataTypes } from 'sequelize';
class User extends Model {}
User.init(
{
username: DataTypes.STRING,
email: DataTypes.STRING,
password: DataTypes.STRING,
},
{ sequelize, modelName: 'user' },
);
class Location extends Model {}
Location.init(
{
locationName: DataTypes.STRING,
},
{ sequelize, modelName: 'location' },
);
class Item extends Model {}
Item.init(
{
itemName: DataTypes.STRING,
orderDate: DataTypes.STRING,
},
{ sequelize, modelName: 'item' },
);
User.hasMany(Item);
Location.hasMany(Item);
Item.belongsTo(User);
Item.belongsTo(Location);
(async function test() {
try {
await sequelize.sync({ force: true });
await User.create(
{
username: 'ddavids',
email: 'hello@david.com',
password: '12345678',
items: [
{
itemName: 'Good Book',
orderDate: '2020-01-20',
location: { locationName: 'floor' },
},
{
itemName: 'Bad Book',
orderDate: '2020-01-21',
location: { locationName: 'shelf' },
},
],
},
{
include: [{ model: Item, include: [Location] }],
},
);
} catch (error) {
console.log(error);
} finally {
await sequelize.close();
}
})();
执行以上代码后,查看数据库中的数据记录:
node-sequelize-examples=# select * from "user";
id | username | email | password
----+----------+-----------------+----------
1 | ddavids | hello@david.com | 12345678
(1 row)
node-sequelize-examples=# select * from "location";
id | locationName
----+--------------
1 | floor
2 | shelf
(2 rows)
node-sequelize-examples=# select * from "item";
id | itemName | orderDate | userId | locationId
----+-----------+------------+--------+------------
1 | Good Book | 2020-01-20 | 1 | 1
2 | Bad Book | 2020-01-21 | 1 | 2
(2 rows)
按预期插入数据记录。
续集版本:"sequelize": "^5.21.3",
源代码:https://github.com/mrdulin/node-sequelize-examples/tree/master/src/examples/Whosebug/59937776