Javascript 如何在查询中通过表获取属性?

Javascript 如何在查询中通过表获取属性?,javascript,node.js,sequelize.js,Javascript,Node.js,Sequelize.js,我在做一个简单的购物车。我有一个购物车模型,一个产品模型和一个表CartItems。这些是协会: models.Cart.belongsToMany(models.Product, { through: 'CartItems', as: 'items' }) models.Product.belongsToMany(models.Cart, { through: "CartItems" }); 以下是模型的定义: 购物车型号 var Cart = sequelize.define('Cart'

我在做一个简单的购物车。我有一个购物车模型,一个产品模型和一个表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
});
产品型号

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型号 在这个模型中,我添加了一个quantity和price属性,因为我在某个地方读到,有一个他们下订单时价格的历史记录是很好的。还有quantity属性,因为我只想在添加另一个产品时更改数量,而不是添加另一行

var CartItem = sequelize.define('CartItem', {
    CartId: DataTypes.INTEGER,
    ProductId: DataTypes.INTEGER,
    quantity: DataTypes.INTEGER,
    price: DataTypes.FLOAT
});
我知道这可能不是做事情的最佳方式,但即使我更改了实现,我也想知道:如何访问through表中的属性

具体而言,我尝试对签出功能执行以下操作:

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;
};
首先是一些警告 警告1。您的
产品
型号和
CartItem
型号中都有一个
价格
字段。你确定要这个吗?在您尝试编写
checkout()
方法时,当您执行
item.price
时,您希望获得哪些价格?我的直觉告诉我,你并不真的想拥有两个字段,但是如果你真的想这样做,考虑重新命名其中一个以避免歧义。 警告2。您的
购物车中有一个
总价
。。。该字段是否应该跟踪相关产品的价格总和?如果是,这是一个坏主意,请将该字段全部删除,并且在需要求和时,立即计算该字段,因为这样保存重复数据非常容易出错(您必须确保它们是同步的)


错误1 您使用以下代码明确定义了连接表模型,即
CartItem

var CartItem = sequelize.define('CartItem', { /* ... */ });
到目前为止还不错。但是当你定义多对多关系时,你犯了一个错误。您通过“CartItems”
使用了
,但您应该通过“CartItem”
使用
。实际上,这种情况下的最佳实践是直接引用模型,因为您有:
到:CartItem
。由于这个原因,Sequelize最终忽略了您的模型并自动创建了一个连接表,而没有额外的字段
price
quantity


错误2 在尝试编写
checkout()
方法时,您执行了以下操作:

this.getItems({
    include: [{
        model: Product,
        through: {
            attributes: ['quantity'],
        }
    }]
});
这是没有道理的。回想一下,
只是为
产品
设置的别名。运行此代码会产生
SequelizeAgerLoadingError:产品与产品不关联

相反,您只需执行
this.getItems()
,而无需任何参数


错误3 接下来,您编写了代码:

return {
    code: item.code,
    price: item.price,
    quantity: item.quantity
};
这表明您希望
quantity
作为
code
旁边的另一个字段出现。这是不正确的<代码>代码
是来自
产品
模型的字段,
数量
是来自
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.CartItem.quantity
,而不是那里的
item.quantity


总结 标题“如何在查询中从through表中获取属性?”中的问题的答案是“只需执行查询,即在您的情况下,
this.getItems()
,因为through表中的属性默认会出现在结果中”


只是你犯了一些其他的错误,当然,它不起作用。

有价格历史记录很好,但你不需要根据数量更新价格。你应该把它和数量相乘得到它。如果有折扣的话,把它也放在那张表上。所以你可以稍后再看。