Подтвердить что ты не робот

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. Также я не хотел бы использовать необработанные запросы.

4b9b3361

Ответ 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