Sequelize с NodeJS не может присоединиться к таблицам с ограничением
Я пытаюсь реализовать простой запрос, который должен выглядеть следующим образом:
select * from property join entity_area on property.id=entity_area.entity_id and entity_area.area_id=1 where property.price>300000 limit 12
Довольно просто: я хочу получить объединенный результат, а затем ограничить до 12.
В Sequelize я использую следующую функцию:
return models.property.findAll(
{
where: ["price>=?", 300000],
include: [
{
model:models.entity_area,
where: { area_id:1 }
}
],
limit:12
})
Но этот код генерирует следующий sql:
select property.*, entity_area.* from (select * from property where property.price>300000 limit 12) join entity_area on property.id=entity_area.entity_id and entity_area.area_id=1
У меня совершенно другая логика из того, что я пытаюсь сделать, потому что в сгенерированном sql он сначала получает любые 12 результатов, а затем пытается присоединиться к entity_area, и, конечно, случайные 12 результатов не обязательно совпадают с entity_area, поэтому я не получаю никаких результатов.
Пожалуйста, предложите мне правильный способ сделать это. Таблица свойств очень массивная, и я должен использовать "предел", а не получать все результаты и нарезать их в javascript. Также я не хотел бы использовать необработанные запросы.
Ответы
Ответ 1
На самом деле я нашел решение самостоятельно. Я думаю, что это ошибка в сиквелизующей структуре.
В node_modules/sequelize/lib/dialect/abstract/query_generator.js есть функция selectQuery, которая имеет следующую строку:
subQuery = limit && (options.hasIncludeWhere || options.hasIncludeRequired || options.hasMultiAssociation) && options.subQuery !== false
Прежде всего, существует опция subQuery, которая может быть передана как ложная, чтобы удалить генерацию подзапроса. В документации Sequelize нет ни слова об этом. Но, кроме того, если вы передадите subQuery: false в объекте findAll, он не будет работать, потому что по какой-то причине он становится недофинансированным функции selectQuery.
Я попробовал что-то вроде:
return models.property.findAll(
{
where: ["price>=?", 300000],
include: [
{
model:models.entity_area,
where: { area_id:1 }
}
],
limit:12,
subQuery:false
})
и все еще получили options.subQuery = undefined.
Итак, мне пришлось изменить функцию в query_generator.js, чтобы быть чем-то вроде:
subQuery = limit && (options.hasIncludeWhere || options.hasIncludeRequired || options.hasMultiAssociation) && options.subQuery !== false && options.doSubQuery===true
Итак, теперь по умолчанию это не делает этот уродливый подзапрос, если я не укажу явно doSubQuery: true. И, наконец, я получил правильный запрос без подзапроса с лимитом.
Ответ 2
models.property.findAll(
{
where: [...],
include: [{...}],
limit:12
},
{
subQuery:false
})
Ответ 3
У меня была эта проблема в последнее время с использованием sequelize 4.28.6, это то, что сработало для меня
User.findAll(
{
where: {
$Tasks$: null,
},
include: [
{
model: Task,
// required: false,
},
],
limit: 3,
subQuery: false,
})
@yuriscom ответ по-прежнему работает, но я не хотел редактировать секвестированную кодовую базу, так как проблема исправлена и добавление subQuery: false,
works