'use strict'
import { Model } from 'sequelize'
class Product extends Model {
static associate({
Brand,
Category,
SKU,
FlashSale,
Tag,
Tax,
Label,
Order,
FlashSaleItem,
OrderItem,
ProductCategory,
ProductLabel,
ProductTag,
ProductTax,
Collection,
CollectionProduct,
Review
}) {
this.belongsTo(Brand, {
foreignKey: 'brandId',
as: 'brand'
})
this.belongsToMany(Category, {
foreignKey: 'productId',
through: ProductCategory,
as: 'categories'
})
this.hasMany(SKU, {
foreignKey: 'productId',
as: 'skus'
})
this.belongsToMany(FlashSale, {
through: FlashSaleItem,
foreignKey: 'productId',
otherKey: 'flashSaleId',
as: 'flashSales'
})
this.belongsToMany(Tag, {
through: ProductTag,
foreignKey: 'productId',
otherKey: 'tagId',
as: 'tags'
})
this.belongsToMany(Tax, {
through: ProductTax,
foreignKey: 'productId',
otherKey: 'taxId',
as: 'taxes'
})
this.belongsToMany(Label, {
through: ProductLabel,
foreignKey: 'productId',
otherKey: 'labelId',
as: 'labels'
})
this.belongsToMany(Order, {
foreignKey: 'productId',
otherKey: 'orderId',
through: OrderItem,
as: 'products'
})
this.belongsToMany(Collection, {
foreignKey: 'productId',
otherKey: 'collectionId',
through: CollectionProduct,
as: 'collections'
})
this.hasMany(Review, {
foreignKey: 'productId',
as: 'reviews'
})
}
}
export default (sequelize, { BIGINT, INTEGER, STRING, TEXT, DECIMAL, JSON }) => {
Product.init(
{
brandId: BIGINT,
name: STRING,
code: STRING,
description: TEXT,
status: STRING,
isFeatured: INTEGER,
price: DECIMAL,
salePrice: DECIMAL,
quantity: INTEGER,
image: STRING,
images: JSON,
hasVariants: INTEGER
},
{
sequelize,
modelName: 'Product',
tableName: 'Products'
}
)
return Product
}
'use strict'
import { Model } from 'sequelize'
class FlashSale extends Model {
static associate({ Product, FlashSaleItem, SKU }) {
this.belongsToMany(Product, {
through: FlashSaleItem,
foreignKey: 'flashSaleId',
otherKey: 'productId',
as: 'products'
})
this.belongsToMany(SKU, {
through: FlashSaleItem,
foreignKey: 'flashSaleId',
otherKey: 'skuId',
as: 'skus'
})
}
}
export default (sequelize, { DATE, STRING }) => {
FlashSale.init(
{
name: STRING,
startDate: DATE,
endDate: DATE,
status: STRING
},
{
sequelize,
modelName: 'FlashSale',
tableName: 'FlashSales'
}
)
return FlashSale
}
'use strict'
import { Model } from 'sequelize'
class FlashSaleItem extends Model {
static associate({ Product, FlashSale }) {
this.belongsTo(Product, {
foreignKey: 'productId',
as: 'product'
})
this.belongsTo(FlashSale, {
foreignKey: 'flashSaleId',
as: 'flashSale'
})
}
}
export default (sequelize, { BIGINT, DECIMAL, INTEGER }) => {
FlashSaleItem.init(
{
flashSaleId: BIGINT,
productId: BIGINT,
skuId: BIGINT,
salePrice: DECIMAL,
quantity: INTEGER
},
{
sequelize,
modelName: 'FlashSaleItem',
tableName: 'FlashSaleItems'
}
)
return FlashSaleItem
}
import db from '@models/index'
import BaseRepository from '@repositories/base.repository'
import FLASH_SALES_STATUS from '@constants/flash.sale.status'
import { Op } from 'sequelize'
class ProductRepository extends BaseRepository {
constructor() {
super(db.Product)
}
async getProductDetail(id) {
return this.findOrFail(id, [
{
model: db.Brand,
as: 'brand'
},
{
model: db.Category,
as: 'categories',
through: { attributes: [] }
},
{
model: db.Tag,
as: 'tags',
through: { attributes: [] }
},
{
model: db.Label,
as: 'labels',
through: { attributes: [] }
},
{
model: db.Collection,
as: 'collections',
through: { attributes: [] }
},
{
model: db.SKU,
as: 'skus',
include: [
{
model: db.AttributeOption,
as: 'attributeOptions',
through: { attributes: [] },
include: [
{
model: db.Attribute,
as: 'attribute'
}
]
},
{
model: db.FlashSale,
as: 'flashSales',
where: {
status: FLASH_SALES_STATUS.PUBLISHED,
startDate: { [Op.lte]: new Date() },
endDate: { [Op.gte]: new Date() }
},
through: {
attributes: ['salePrice', 'quantity'],
as: 'pivot'
},
order: [['startDate', 'DESC']],
limit: 1,
required: false
}
]
},
{
model: db.FlashSale,
as: 'flashSales',
where: {
status: FLASH_SALES_STATUS.PUBLISHED,
startDate: { [Op.lte]: new Date() },
endDate: { [Op.gte]: new Date() }
},
through: {
attributes: ['salePrice', 'quantity'],
as: 'pivot'
},
order: [['startDate', 'DESC']],
limit: 1,
required: false
}
])
}
}
export default ProductRepository
当我添加订单和限价时。 Sequelize 抛出错误:只有 HasMany 关联支持 include.separate。 我使用Sequelize“sequelize”:“^ 6.37.5”和“mysql2”:“^ 3.11.3”
我尝试编写范围和包含范围,但仍然无法限制元素的数量。我寻找 Sequelize 问题的解决方案。
对于 Sequelize 中的
ORDER
和 LIMIT
多对多关联:
单独查询:先获取
Product
,然后与flashSales
和ORDER
分别查询LIMIT
,并手动附上结果。
const product = await this.findOrFail(id, {/* other includes, exclude flashSales */});
const flashSales = await db.FlashSale.findAll({
where: { /* conditions */ },
include: [{ model: db.Product, where: { id: product.id } }],
order: [['startDate', 'DESC']],
limit: 1
});
product.dataValues.flashSales = flashSales;
Scope:在
recentSales
中定义一个FlashSaleItem
范围,以便在查询时应用ORDER
和LIMIT
。
static scopes() {
return {
recentSales: {
include: [{ model: db.FlashSale, where: { /* conditions */ }, order: [['startDate', 'DESC']], limit: 1 }]
}
};
}
建议使用单独的查询来绕过 Sequelize 对多对多关系的
include.separate
限制。