【问题标题】:Sequelize - Can't limit properly query with includes, using hasMany and belongsToMany associationsSequelize - 使用 hasMany 和 belongsToMany 关联无法正确限制包含的查询
【发布时间】:2022-01-25 02:41:27
【问题描述】:

问题说明

我想做一个分页查询,每个查询限制为 12 行,更具体地说,每个查询限制为 12 Batches。实际上,行数变小了,因为belongsToMany 与我在此查询中得到的连接表关联。这个查询的连接顺序是:Offer > hasMany > Batch > belongsToMany > BatchFile > belongsTo > File。问题是,当我在File as 'gallery' 关联中有许多注册表时,它会给我带来批量重复的注册表。

我正在尝试执行的查询

const { id } = req.params;
const { page = 1 } = req.query;

const offer = await Offer.findAndCountAll({
  attributes: [ 'id', 'name', 'canceled_at'],
  where: { id, canceled_at: null },
  order: [['offer_batches', 'name', 'ASC']],
  include: [
    {
      /* hasMany association */
      model: Batch,
      as: 'offer_batches',
      attributes: [ 'id', 'name'],
      include: [
        { /* Other includes... */ },
        {
          /* belongsToMany association */
          model: File,
          as: 'gallery',
          attributes: ['id', 'path', 'url'],
        },
      ],
    },
  ],
  subQuery: false,
  limit: 12,
  offset: (page - 1) * 12,
});

模型关联

提供模型

this.hasMany(Batch, { foreignKey: 'offer_id', as: 'offer_batches' });

批量模型

this.belongsToMany(File, { through: models.BatchFile, as: 'gallery' });

BatchFile 模型(连接表)

this.belongsTo(Batch, { foreignKey: 'batch_id', as: 'batch' });
this.belongsTo(File, { foreignKey: 'file_id', as: 'file' });

我已经尝试过的

为任何包含的模型提供duplicating: false 选项不起作用;

separate: true 分配给Batch 模型也不起作用;

为任何包含的模型提供required: true 选项也不起作用;

如果我删除 subQuery: false 它不遵守设置的行数限制,我已经尝试了上述所有组合;

我认为 sequelize 可以毫无问题地处理这种情况,也许我做错了什么。

如果有帮助,这里是原始生成的 SQL:

SELECT
"Offer"."id",
"Offer"."name",
"Offer"."canceled_at",
"offer_batches"."id"
AS "offer_batches.id", "offer_batches"."name"
AS "offer_batches.name", "offer_batches->gallery"."id"
AS "offer_batches.gallery.id", "offer_batches->gallery"."path"
AS "offer_batches.gallery.path", "offer_batches->gallery->BatchFile"."created_at"
AS "offer_batches.gallery.BatchFile.createdAt", "offer_batches->gallery->BatchFile"."updated_at"
AS "offer_batches.gallery.BatchFile.updatedAt", "offer_batches->gallery->BatchFile"."file_id"
AS "offer_batches.gallery.BatchFile.FileId", "offer_batches->gallery->BatchFile"."batch_id"
AS "offer_batches.gallery.BatchFile.BatchId", "offer_batches->gallery->BatchFile"."batch_id"
AS "offer_batches.gallery.BatchFile.batch_id", "offer_batches->gallery->BatchFile"."file_id"
AS "offer_batches.gallery.BatchFile.file_id"
FROM "offer" AS "Offer"
LEFT OUTER JOIN "batch" AS "offer_batches" ON "Offer"."id" = "offer_batches"."offer_id"
LEFT OUTER JOIN (
  "batch_file" AS "offer_batches->gallery->BatchFile"
  INNER JOIN "file" AS "offer_batches->gallery"
  ON "offer_batches->gallery"."id" = "offer_batches->gallery->BatchFile"."file_id"
)
ON "offer_batches"."id" = "offer_batches->gallery->BatchFile"."batch_id"
WHERE "Offer"."id" = '1' AND "Offer"."canceled_at" IS NULL
ORDER BY "offer_batches"."name"
ASC LIMIT 12 OFFSET 0;

环境

节点:v14.18.0

package.json 依赖

  • pg:8.7.1
  • pg-hstore:2.3.4
  • 续集:@​​987654342@

试图在 GitHub 问题或 stackoverflow 上找到任何解决方案,但没有解决这个问题。也许我做错了这个查询,任何帮助将不胜感激和欢迎:)

【问题讨论】:

  • 能否在主模型选项中为subQuery: falseBatch 选项中的separate: true 添加生成的SQL 查询?
  • 我可以试试@Anatoly,你的意思是像在主模型中硬编码一个原始 SQL 查询?我试图避免直接在我的代码上执行此操作,以保持我构建查询的方式的模式,但它可能有效。现在停止思考,我认为用第二种方式可能会更好,因为查询变得非常嵌套
  • 不,只需检索 Sequelize 生成的 SQL 查询,同时尝试使用这些选项执行查询

标签: javascript sql node.js postgresql sequelize.js


【解决方案1】:

好吧,我没有找到一个很好的解决方案,所以我决定在这种情况下使用Lazy loading 而不是Eager loading,正如Sequelize Docs 中提到的那样。

我将查询拆分为两个新查询。

第一个,在“主”模型Offer上,带有一个简单的findOne()

const offer = await Offer.findOne({
  [/* My attributes */],
  where: { /* My conditions */ }
});

第二个,从型号Batch 中选择,没有subQuery: false 选项,因为不再需要。

const batches = await Batch.findAndCountAll({
  attributes: [
    'id',
    'name',
  ],
  where: { offer_id: offer.id },
  order: [/* My ordenation */],
  include: [
    {
      model: File,
      as: 'gallery',
      attributes: ['id', 'path', 'url'],
    },
  ],
  limit: 12,
  offset: (page - 1) * 12,
});

【讨论】:

    猜你喜欢
    • 2023-03-24
    • 2020-08-28
    • 1970-01-01
    • 2019-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-15
    相关资源
    最近更新 更多