У меня есть следующие модели секвенирования:
import { DataTypes, Model } from 'sequelize';
class A extends Model{}
A.init {
name: DataTypes.STRING,
start_date: DataTypes.DATE,
end_date: DataTypes.DATE,
deleted: DataTypes.BOOLEAN
}
class B extends Model {}
B.init {
a_id: DataTypes.Integer,
text: DataTypes.String,
created_at: DataTypes.STRING,
updated_at: DataTypes.DATE,
}
B.belongsTo(A);
A.hasMany(B);
Я пытаюсь выполнить запрос, чтобы получить первые 50 записей A с левым внешним соединением B. По какой-то причине я получаю только 49 записей. Что странно, если я возьму запрос, сгенерированный в свойстве logging, и воспользуюсь таким инструментом, как DBeaver, я получу все 50 строк.
Вот как создается запрос:
const params = {
limit: 50,
offset: 0,
order: [ [ 'id', 'desc']],
attributes: [
'id',
'name',
'start_date',
'end_date',
],
subQuery: false,
where: { deleted: false },
include: [{model: B}],
logging: console.info
}
const results = await A.findAll(params);
//length of results is 49
А вот запрос, который генерируется свойством logging:
(Обратите внимание, что я не включил все столбцы в список для удобства чтения)
SELECT *
FROM "A" LEFT OUTER JOIN B ON "A"."id" = "B"."a_id"
WHERE "A"."deleted" = false
ORDER BY "A"."id" DESC
LIMIT 50 OFFSET 0;
Запрос Sequelize возвращает 49 строк. Запрос, созданный на основе запроса Sequelize, возвращает 50.
Некоторые другие точки данных
Обновлять:
const results = await this.A.findAll(findParams);
console.info('Final results: ', results.length);
Как вы измеряете размер результата, всего console.info(results.length)
? Вы делаете это сразу после оператора findAll
или позже, когда какой-то другой код уже мог мутировать results
? Единственное объяснение, которое я могу придумать, это неосторожный results.pop()
звонок куда-то.
Я обновлю свой вопрос, включив в него ответ на ваш вопрос, @Bergi
Вы можете просто указать separate: true
в опции include
, чтобы добиться правильного результата. Для лучшего объяснения смотрите мой ответ здесь: stackoverflow.com/a/61763084/1376618
Кажется, это исправило ситуацию. Почему по умолчанию не включаются все связанные записи? Какие записи включаются, а какие исключаются? Почему соединение не возвращает все правильные записи? Меня беспокоит снижение производительности при использовании отдельного файла. Кроме того, почему сгенерированный запрос возвращает все правильные записи, а код продолжения — нет? Вот объяснение того, что делает/означает отдельный: stackoverflow.com/questions/37964763/…
По умолчанию Sequelize объединит связанную модель во внутренний массив. Из-за композиции при подсчете длины результата фактически подсчитывается количество различных записей модели A
.
Бывший:
SQL-вывод
| id | name | a_id | text |
| 1 | a1 | 1 | b1 |
| 1 | a1 | 1 | b2 |
| 2 | a2 | 2 | b3 |
Это будет составлено в
[
{
"id": 1,
"name": "a1",
"b" : [
{
"text": "b1"
},
{
"text": "b2"
}
]
},
{
"id": 2,
"name": "a2",
"b": [
{
"text": "b3"
}
]
}
]
Если вы подсчитаете длину родительского массива, вы увидите 2, а вывод SQL — 3. На самом деле вам нужно посчитать количество элементов во внутренних массивах, которое должно соответствовать счетчику SQL.
Если вы не хотите, чтобы Sequelize компоновал таким образом, вы можете отключить эту композицию,
params = {
...
raw: true,
nest: true
}
Я обновил свой экземпляр postgres, чтобы регистрировать все запросы, и появившийся запрос был таким же, как тот, который показывал мне console.info. Этот запрос возвращал все 50 строк.