我正在尝试实现一个看起来像这样的简单查询:
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中切片。此外,我不想开始使用原始查询。
答案 0 :(得分:13)
其实我自己找到了解决方案。我认为这是续集框架中的一个错误 在node_modules / sequelize / lib / dialect / abstract / query_generator.js中有一个“selectQuery”函数,它包含以下行:
subQuery = limit && (options.hasIncludeWhere || options.hasIncludeRequired || options.hasMultiAssociation) && options.subQuery !== false
首先,有一个选项subQuery可以作为false传递,以删除子查询生成。 Sequelize文档没有关于它的说法。但是,如果你在findAll对象中传递subQuery:false,它将不会起作用,因为由于某种原因,它将被定义为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。最后,我得到了没有子查询的正确查询。
答案 1 :(得分:6)
models.property.findAll(
{
where: [...],
include: [{...}],
limit:12
},
{
subQuery:false
})
答案 2 :(得分:2)
我最近使用sequelize 4.28.6遇到了这个问题,这对我有用
User.findAll(
{
where: {
$Tasks$: null,
},
include: [
{
model: Task,
// required: false,
},
],
limit: 3,
subQuery: false,
})
@yuriscom答案仍然有效,但我不想编辑续集代码库,因为问题已修复并添加subQuery: false,
有效