如何对多对多 Sequelize 关系中包含的元素进行排序和限制?只有很多协会支持包括单独的

问题描述 投票:0回答:1
'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.js many-to-many sql-order-by limit
1个回答
0
投票

对于 Sequelize 中的

ORDER
LIMIT
多对多关联:

  1. 单独查询:先获取

    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;
    
  2. Scope:在

    recentSales
    中定义一个
    FlashSaleItem
    范围,以便在查询时应用
    ORDER
    LIMIT

    static scopes() {
      return {
        recentSales: {
          include: [{ model: db.FlashSale, where: { /* conditions */ }, order: [['startDate', 'DESC']], limit: 1 }]
        }
      };
    }
    

建议使用单独的查询来绕过 Sequelize 对多对多关系的

include.separate
限制。

© www.soinside.com 2019 - 2024. All rights reserved.