findAndCountAll count 得到的数字比实际返回的数据大

问题描述 投票:0回答:4

我正在使用 Sequelize

findAndCountAll()
作为我网站的分页。

findAndCountAll()
返回的总项目数(
3990
)大于实际返回的数据数(
3770
)。

有谁知道如何让

findAndCountAll()
返回的总项目数与实际返回的数据相同?

我使用的表

findAndCountAll()
查询包括另外两个表,如下面的代码:

const patientModel: IIncludeOptions = {
    model: Patient,
    attributes: ["deviceId", "firstName", "lastName"],
};

const deviceModel: IIncludeOptions = {
    model: Device,
    required: true,
    attributes: ["deviceId", "deviceSerialNumber"],
    include: [patientModel],
};

const eventCodeModel: IIncludeOptions = {
    model: EventCode,
    required: true,
    attributes: ["name"],
};

const opts: IFindOptions = {
    ...pageSizeLimit,
    offset : offsetNum,
    attributes: ["id", "deviceId", "eventId", "dispatchedAt", "message", "createdAt"],
    include: [
        deviceModel,
        eventCodeModel,
    ],
    order: sortBy,
};

const resCount = await DeviceEvent.findAndCountAll(opts).then((response) => {
    const totalItems = response.count;
    return {
        totalItems,
        currentPage: page || 1,
    };
});
sequelize.js
4个回答
6
投票

对我有用的是将

distinct: true
添加到查询中。如果没有这个 Sequelize 将返回没有内部连接/必需的值的计数:true。

const posts = Post.findAndCountAll({
    include: ['attachment', 'users', 'x count of models'],
    distinct: true
});

在问题中使用的代码中,这将是:

const opts: IFindOptions = {
    ...pageSizeLimit,
    offset : offsetNum,
    attributes: ["id", "deviceId", "eventId", "dispatchedAt", "message", "createdAt"],
    include: [
        deviceModel,
        eventCodeModel,
    ],
    order: sortBy,
    distinct: true,
};

此处提到了详细信息 - findandCountAll 中的计数问题


1
投票

当你有一对多关联时,你必须在你的选项中设置separate: true,例如:

users.findAndCountAll({
include:[{model:messages,as:"messages",separate:true}]
}) 

0
投票

尝试检查 SQL 记录查询。

按照这些说明获取查询转储:如何查看 Sequelize.js 生成的 SQL?

并查看计数是否与

findAndCountAll()
返回给您的计数相同。

也许

sequelize.js
安装查询的方式会影响结果。


0
投票

Sequelize 正在为 findAndCountAll 执行两个查询 - 一个用于执行原始查询,另一个用于计算记录数。 这种方法有两个问题:

  • 首先是sequelize执行不必要的连接来计算记录。您不需要进行这些连接。
  • 此外,在某些情况下,这些额外的连接会导致续集返回错误的记录数作为计数。在我的例子中,计数是 26 而不是 4。

使用distinct=true可以解决某些情况下的问题。但在另一种情况下问题仍然相同,并导致返回错误的数字作为计数。

我通过创建我的方法想出了一个解决方案。 一个用于执行源查询,另一个用于统计记录。

import { Attributes, FindAndCountOptions, ModelStatic } from 'sequelize';
import { Model } from 'sequelize-typescript';

Using nest js and sequelize-typescript
/**
 * This is a workaround for the issue
 * sequlize do an extra join for counting the number of records.
 * This is a problem when you have a lot of records and you want to count them
 * also in some cases sequelize returns a WRONG number of records which is another problem
 * for the method findAndCountAll sequelize do two queries. one for counting and one for getting the records
 * Here I added a new method findAndCountAllCorrectly which does the same thing but without extra joins and also in the correct way
 * *IMPORTANT: instead of using findAndCountAll use findAndCountAllCorrectly. For this, you need to extend
 * *your model from CustomModel instead of Model
 */

export class CustomModel<T> extends Model<T> {
  public static async findAndCountAllCorrectly<M extends Model>(
    this: ModelStatic<M>,
    options?: Omit<FindAndCountOptions<Attributes<M>>, 'group'>,
  ): Promise<{ rows: M[]; count: number }> {
    const itemsPromise = super.findAll<M>(options);
    const countPromise = super.count({ where: options?.where });
    console.log(
      'hi im going the count all records without extra joins and most importantly in a correct way',
    );
    const [items, count] = await Promise.all([itemsPromise, countPromise]);
    // const count = countGroup[0].count;
    return { rows: items, count };
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.