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

时间:2018-03-10 11:48:04

标签: 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', {
    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;
};

1 个答案:

答案 0 :(得分:1)

首先,一些警告

警告1。您的price模型和Product模型中都有CartItem字段。你确定要这个吗?在您尝试编写checkout()方法时,当您执行item.price时,您希望获得哪些价格?我的直觉告诉我你并不是真的想拥有两个领域,但如果你真的这样做,可以考虑重新命名其中一个以避免含糊不清。

警告2。您的totalPrice型号中有Cart ...此字段是否应跟踪相关产品的价格总和?如果是,那是一个坏主意,完全删除该字段,并在需要总和时,在那个时刻进行计算,因为保留这样的重复数据非常容易出错(必须确保它们是同步的)。

错误1

您使用以下代码明确定义了联结表模型,即CartItem

var CartItem = sequelize.define('CartItem', { /* ... */ });

到目前为止一切顺利。但是当你定义多对多关系时,你犯了一个错误。您使用了through: "CartItems",但您应该使用through: "CartItem"。实际上,在这种情况下,最佳做法是直接引用模型,因为您拥有它:through: CartItem。因此,Sequelize最终忽略了您的模型并自动创建了一个联结表而没有您的额外字段pricequantity

错误2

在您尝试编写checkout()方法时:

this.getItems({
    include: [{
        model: Product,
        through: {
            attributes: ['quantity'],
        }
    }]
});

这没有意义。回想一下,Item只是您为Product设置的别名。运行此代码会产生SequelizeEagerLoadingError: Product is not associated to Product!

相反,您可以简单地执行this.getItems()而不需要任何参数。

错误3

接下来,您编写了代码:

return {
    code: item.code,
    price: item.price,
    quantity: item.quantity
};

这表明您希望quantitycode并列为另一个字段。这是不正确的。 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(),因为来自表格的属性默认情况下会出现在结果中。“

只是你犯了一些其他的错误,当然,它没有用。