我正在制作一个简单的购物车。我有一个购物车模型,一个产品型号和一个通过表CartItems。这些是协会:
models.Cart.belongsToMany(models.Product, { through: 'CartItems', as: 'items' })
models.Product.belongsToMany(models.Cart, { through: "CartItems" });
以下是模型的定义:
购物车型号
var Cart = sequelize.define('Cart', {
userId: {
allowNull: false,
type: Sequelize.INTEGER,
references: {
model: 'User',
key: 'id',
},
},
totalPrice: DataTypes.FLOAT
});
产品型号
var Product = sequelize.define('Product', {
code: DataTypes.STRING,
name: DataTypes.STRING,
price: DataTypes.FLOAT
});
CartItems模型 在这个模型中,我添加了一个数量和价格属性,因为我在某个地方读到,有一个关于订单生产时的价格历史的好消息。还有数量属性,因为我只想添加另一个产品而不是添加另一行来更改数量。
var CartItem = sequelize.define('CartItem', {
CartId: DataTypes.INTEGER,
ProductId: DataTypes.INTEGER,
quantity: DataTypes.INTEGER,
price: DataTypes.FLOAT
});
我知道这可能不是最好的做事方式,但即使我改变了实现,我也想知道:如何访问到表中的属性?
具体来说,我正在尝试为结帐功能执行以下操作:
Cart.prototype.checkout = async function () {
let cartItemArray = await this.getItems({
include: [{
model: Product,
through: {
attributes: ['quantity'],
}
}]
});
cartItemArray = cartItemArray.map((item) => {
return {
code: item.code,
price: item.price,
quantity: item.quantity
};
});
let total = getTotalPrice(cartItemArray);
return total;
};
答案 0 :(得分:1)
警告1。您的price
模型和Product
模型中都有CartItem
字段。你确定要这个吗?在您尝试编写checkout()
方法时,当您执行item.price
时,您希望获得哪些价格?我的直觉告诉我你并不是真的想拥有两个领域,但如果你真的这样做,可以考虑重新命名其中一个以避免含糊不清。
警告2。您的totalPrice
型号中有Cart
...此字段是否应跟踪相关产品的价格总和?如果是,那是一个坏主意,完全删除该字段,并在需要总和时,在那个时刻进行计算,因为保留这样的重复数据非常容易出错(必须确保它们是同步的)。
您使用以下代码明确定义了联结表模型,即CartItem
:
var CartItem = sequelize.define('CartItem', { /* ... */ });
到目前为止一切顺利。但是当你定义多对多关系时,你犯了一个错误。您使用了through: "CartItems"
,但您应该使用through: "CartItem"
。实际上,在这种情况下,最佳做法是直接引用模型,因为您拥有它:through: CartItem
。因此,Sequelize最终忽略了您的模型并自动创建了一个联结表而没有您的额外字段price
和quantity
。
在您尝试编写checkout()
方法时:
this.getItems({
include: [{
model: Product,
through: {
attributes: ['quantity'],
}
}]
});
这没有意义。回想一下,Item
只是您为Product
设置的别名。运行此代码会产生SequelizeEagerLoadingError: Product is not associated to Product!
。
相反,您可以简单地执行this.getItems()
而不需要任何参数。
接下来,您编写了代码:
return {
code: item.code,
price: item.price,
quantity: item.quantity
};
这表明您希望quantity
与code
并列为另一个字段。这是不正确的。 code
是来自Product
模型的字段,而quantity
是来自CartItem
模型的字段。 Sequelize不会像这样检索它们“扁平化”。相反,关联本身的字段嵌套在查询结果中,如下所示:
{
"id": 1,
"code": null,
"name": "test",
"price": null,
"createdAt": "2018-03-11T19:11:12.862Z",
"updatedAt": "2018-03-11T19:11:12.862Z",
"CartItem": {
"CartId": 1,
"ProductId": 1,
"quantity": 2,
"price": 1.5,
"createdAt": "2018-03-11T19:11:13.047Z",
"updatedAt": "2018-03-11T19:11:13.047Z"
}
}
因此,您应该使用item.quantity
而不是item.CartItem.quantity
。
标题中问题的答案,“如何通过查询中的表格获取属性?”只是“只是在您的情况下执行查询,即this.getItems()
,因为来自表格的属性默认情况下会出现在结果中。“
只是你犯了一些其他的错误,当然,它没有用。