Subqueries and missing fields, again
See original GitHub issueNote: This post is to describe the problem, I posted a reply with a suggested solution approach below.
What you are doing?
- do a find
- include 1:n association
- limit the outer query
- filter on the outer query (top-level
where
) with a “nested” key, e.g.$child.childAttribute$: 1337
- no, I cannot filter on the include, because I need to AND/OR-combine the childAttribute condition with some other condition on the outer/parent model
var Parent = sequelize.define('Parent', {name: Sequelize.STRING}, {timestamps: false});
var Child = sequelize.define('Child', {name: Sequelize.STRING}, {timestamps: false});
Parent.hasMany(Child, {as: 'children', foreignKey: 'parentId'});
Child.belongsTo(Parent, {as: 'child', foreignKey: 'parentId'});
async function run() {
await sequelize.sync();
const p1 = await Parent.create({name: 'p1'});
const p2 = await Parent.create({name: 'p2'});
const c1 = await Child.create({name: 'c1', parentId: p1.id});
const c2 = await Child.create({name: 'c2', parentId: p1.id});
const c3 = await Child.create({name: 'c3', parentId: p2.id});
const c4 = await Child.create({name: 'c4', parentId: p2.id});
const p = await Parent.findAll({
where: {
$or: {
name: 'p1',
'$children.name$': 'c3',
},
},
include: [{model: Child, as: 'children'}],
limit: 1,
order: [['name', 'ASC']],
});
console.log(JSON.stringify(p.map(p => p.toJSON()), null, 4));
}
run().catch((err) => console.error(err));
What do you expect to happen?
I would like to receive one parent (p1
, thanks to name ordering) for which the filter holds (the name matches ‘p1’), including ALL their children (c1
and c2
) (since I’m not filtering on them, just filtering on the parent relation).
What is actually happening?
It breaks with ER_BAD_FIELD_ERROR: Unknown column because the LIMIT is applied in the subquery, but the JOIN isn’t.
I cannot move the where
condition for the children into the include
, since then I would only receive those children, not ALL children of the matching parents. Also I could not combine that condition using $or
with the name condition on the parent.
Dialect: mysql Database version: irrelevant Sequelize version: 4.0.0-0
Issue Analytics
- State:
- Created 7 years ago
- Comments:6 (6 by maintainers)
Bump.
I fiddled around a little with the SQL generated. I think one possible solution would be to
LEFT OUTER JOIN
in the subquery, just like in the outer queryLIMIT
onWHERE
, but beforeLIMIT
by usingGROUP BY
on primary key attributes of the main tablewhere
inside theinclude
would generate theWHERE
condition outside the subquery, nothing changed there eitherBefore
After
Things to decide
attributes
etc.?limit
ing andorder
ing) which would break if there were more joins?How to implement
Apart from that, the implementation seems not too bad, simply add a “default” GROUP BY on each subquery, and all
mainJoinQueries
to thesubJoinQueries
in the abstract query generator. I tried it, it worked for my use case.