Можно ли выполнить подзапрос с помощью Sequelize.js?

У меня есть запрос, который выглядит так:

select es.EssayId, (esmax.WordCount - esmin.WordCount)
from (select es.EssayId, min(es.EssayDate) as mined, max(es.EssayDate) as maxed
      from EssayStats es
      group by es.EssayId
     ) es join
     EssayStats esmin
     on es.EssayId = esmin.EssayId and es.mined = esmin.EssayDate join
     EssayStats esmax
     on es.EssayId = esmax.EssayId and es.maxed = esmax.EssayDate;

Можно ли написать это с помощью Sequelize.js ORM? Я знаю, что могу просто использовать query напрямую, но мне интересно, можно ли его построить.

Ответ 1

Я не думаю, что возможен чистый ответ на ваш вопрос. См. # 1869:

В настоящее время неудачно невозможно выполнить запрос на сквозную модель/таблицу соединений.

Чтобы ответить на вопрос заголовка, Sequelize автоматически сгенерирует подзапрос (например, # 1719), но вы не можете выполнить пользовательский подзапрос. У меня нет авторитетной ссылки на негатив.


Похоже, ваша таблица выглядит примерно так:

EssayStats
    EssayId
    EssayDate
    WordCount

Тогда вы можете сделать что-то вроде этого:

return EssayStat.findAll({
    attributes: [
        [sequelize.literal('((SELECT wordCount FROM "EssayStats" WHERE "EssayId" = "EssayStat"."EssayId" EssayStat BY "createdAt" DESC LIMIT 1) - (SELECT wordCount FROM "EssayStats" WHERE "EssayId" = "EssayStat"."EssayId" EssayStat BY "createdAt" ASC LIMIT 1))'), 'difference'],
        'EssayId'
    ],
    group: ['EssayId']
});

Все, что он делает, запускает два запроса SELECT, беря MAX и MIN из этих запросов после заказа вашей переменной, представляющей интерес, и затем принимая во внимание вашу разницу. Это даст вам то, что вас интересует: разность слов между самой последней версией и первой версией.

Трюк здесь заключается в инкапсуляции оператора SELECT в поле атрибута.

Конечно, это грязно, как черт, и, вероятно, не так уж много, чем консервированный sequelize.query. Но он отвечает на суть вашего вопроса.

Лучшим решением может быть денормализация ваших данных и хранение "wordCountDelta" непосредственно в вашей модели Essay. Тогда вы можете иметь afterCreate hook для автоматического обновления поля. Это, скорее всего, будет самым быстрым решением.

Я ответил на что-то подобное здесь.

Ответ 2

пример для подзапроса

ModelA.findAll({
    where: {
        $or: [
            {'$B.someColumn$' : someCondition},
            {'$C.someOtherColumn$' : someOtherCondition}
        ]
    },
    include: [{
        model: ModelB,
        required: false,  //true or false for required 
        where:{id:$id}

    }, {
        model: ModelC,
        required: false, //true or false for required 
        where:{id:$id}
    }]
}); 

Надеюсь, полезно: D