Currently I've got a solution with the following raw query, which works well.
Here's a SqlFiddle playground.
And here's the raw query that works well:
const sql = `SELECT u.*, g.name AS "gender"
FROM users u
INNER JOIN connections con ON con.user_id = u.id
INNER JOIN completed_quizzes q ON q.user_id = u.id
LEFT JOIN genders g ON g.id = u.gender_id
WHERE
con.other_user_id='foo'
AND q.quiz_id=1
AND con.status='approved'
AND u.deleted_at IS NULL
AND con.deleted_at IS NULL
AND q.deleted_at IS NULL
LIMIT 10
OFFSET 0
`;
But I'm trying to replace it with Sequelize's object modelling. So far, the most meaningful solution I've come up with this:
const sequelize = {
include: [
{
model: ConnectionsModel,
as: 'connections',
where: { otherUserId: userId, status: ConnectionStatus.approved },
required: true,
duplicating: false
},
{
model: CompletedQuizzesModel,
as: 'completedQuizzes',
where: { userId, quizId },
required: true,
duplicating: false
},
{
model: GendersModel
}
],
nest: true,
// have to specify `raw: false`, otherwise Sequelize returns only the first associated record
raw: false
};
It generates the following query (I've prettified it, for ease of reading):
SELECT u.*, g.name AS gender FROM users AS u
INNER JOIN connections AS con ON u.id = con.user_id AND (con.status = 'approved' AND con.other_user_id = 'foo')
INNER JOIN completed_quizzes AS q ON u.id = q.user_id AND (q.user_id = 'foo' AND q.quiz_id = '1')
LEFT OUTER JOIN genders AS g ON u.gender_id = g.id
WHERE u.deleted_at IS NULL
LIMIT 20
OFFSET 0;
But it returns nothing... no rows. Whereas, the original solution returns the rows as needed.
I can see the difference between the general where (which is applied to the whole query in the raw query) and the same attributes appended to the on clause in the joins. Not sure if that's the problem, though.
Here's the SqlFiddle playground again.
You added an extra condition in the include option CompletedQuizzesModel. In the original SQL query you don't have a condition on userId.
So this include should be like this:
{
model: CompletedQuizzesModel,
as: 'completedQuizzes',
where: { quizId }, // removed userId
required: true,
duplicating: false
}
The result query works just like the original one:
SELECT u.*, g.name AS gender FROM users AS u
INNER JOIN connections AS con ON u.id = con.user_id AND (con.status = 'approved' AND con.other_user_id = 'foo')
INNER JOIN completed_quizzes AS q ON u.id = q.user_id AND (q.quiz_id = '1')
LEFT OUTER JOIN genders AS g ON u.gender_id = g.id
WHERE u.deleted_at IS NULL
LIMIT 20
OFFSET 0;
Related
I'm trying to accomplish the task of joining all associated models, and then retrieving the count of all the models
I would want the data to be returned as
product {
main_dish: {},
side_dish: {},
drink: {},
purchase_product_count: x,
purchased_products: []
}
I have constructed this in sequelize to try to do this.
await Product.findAll({
include: [{
model: MainCourse,
required: false,
}, {
model: SideDish,
required: false,
}, {
model: Drink,
required: false,
}, {
model: ProductPurchase,
required: false,
where: {
createdAt: {[Op.between]: [two_days_before, current_date]}
},
}],
attributes: {
include: ['*',
[Sequelize.literal(
"(SELECT COUNT(*) from product_purchases as p where p.purchase_product_id = products.product_id)"), "product_purchase_count"],
]
},
offset: 1 * 5,
limit: 5
})
.then((results) => {
console.log(results)
res.status(200).json(results)
})
.catch((err) => {
console.log(err)
res.status(400).json(err)
})
Attempting to run this eager load gives this error
column reference "product_id" is ambiguous
This is the sql generated by sequelize
SELECT "products".*, "main_course"."main_course_id" AS "main_course.main_course_id", "main_course"."type" AS "main_course.type", "main_course"."createdAt" AS "main_course.createdAt", "main_course"."updatedAt" AS "main_course.updatedAt", "main_course"."deletedAt" AS "main_course.deletedAt", "main_course"."main_product_id" AS "main_course.main_product_id", "side_dish"."side_dish_id" AS "side_dish.side_dish_id", "side_dish"."type" AS "side_dish.type", "side_dish"."createdAt" AS "side_dish.createdAt", "side_dish"."updatedAt" AS "side_dish.updatedAt", "side_dish"."deletedAt" AS "side_dish.deletedAt", "side_dish"."side_product_id" AS "side_dish.side_product_id", "drink"."drink_id" AS "drink.drink_id", "drink"."type" AS "drink.type", "drink"."createdAt" AS "drink.createdAt", "drink"."updatedAt" AS "drink.updatedAt", "drink"."deletedAt" AS "drink.deletedAt", "drink"."drink_product_id" AS "drink.drink_product_id", "product_purchases"."product_purchase_id" AS "product_purchases.product_purchase_id", "product_purchases"."price" AS "product_purchases.price", "product_purchases"."quantity" AS "product_purchases.quantity", "product_purchases"."createdAt" AS "product_purchases.createdAt", "product_purchases"."updatedAt" AS "product_purchases.updatedAt", "product_purchases"."deletedAt" AS "product_purchases.deletedAt", "product_purchases"."purchase_product_id" AS "product_purchases.purchase_product_id", "product_purchases"."restaurant_order_id" AS "product_purchases.restaurant_order_id" FROM (SELECT "products"."product_id", "products"."title", "products"."price", "products"."createdAt", "products"."updatedAt", "products"."deletedAt", "products"."restaurant_id", "products".*, (SELECT COUNT(*) from product_purchases as p where p.purchase_product_id = products.product_id) AS "product_purchase_count" FROM "products" AS "products" WHERE ("products"."deletedAt" IS NULL) LIMIT 5 OFFSET 5) AS "products" LEFT OUTER JOIN "main_courses" AS "main_course" ON "products"."product_id" = "main_course"."main_product_id" AND ("main_course"."deletedAt" IS NULL) LEFT OUTER JOIN "side_dishes" AS "side_dish" ON "products"."product_id" = "side_dish"."side_product_id" AND ("side_dish"."deletedAt" IS NULL) LEFT OUTER JOIN "drinks" AS "drink" ON "products"."product_id" = "drink"."drink_product_id" AND ("drink"."deletedAt" IS NULL) LEFT OUTER JOIN "product_purchases" AS "product_purchases" ON "products"."product_id" = "product_purchases"."purchase_product_id" AND ("product_purchases"."deletedAt" IS NULL AND "product_purchases"."createdAt" BETWEEN '2022-05-06 08:35:12.577 +00:00' AND '2022-05-08 08:35:12.577 +00:00');
According to pgadmin the problem starts when doing the join on main_courses
ERROR: column reference "product_id" is ambiguous
LINE 1: ...EFT OUTER JOIN "main_courses" AS "main_course" ON "products"...
I seem to not understand how the sequelize join works as I am using the ORM method of not having any columns be the same. The foreign keys are all different from 'product_id'. Is product_id getting created and joined again on the aggregation possibly? Why am I getting this error, and how can I achieve the result of getting the count of the product_purchases along with the joined array of purchased products.
Obviously I could just get the purchased_products.length and then add it to the object itself, but I'm trying to figure out if you can do it through sequelize without having to hack it in.
I have 3 tables named:
//restaurants
columns ( id, name, restaurant_type_id(FK)
//restaurant_branches
columns ( id, name, restaurant_id(FK)
//restaurant_types
columns ( id, restaurant_type_name('italian', 'french'...etc))
I would like to filter restaurant_branches by restaurant_type_id using query params in my restaurant_branches.findAll(); action in the controller as the following.
const findAll = async (req, res) => {
let RestaurantTypeId= req.query.restaurantType ? parseInt(req.query.restaurantType): null ;
var type = RestaurantTypeId ? {where:{ restaurantTypeId: RestaurantTypeId }} : null ;
console.log(RestaurantTypeId);
await RestaurantBranch.findAll({
order: [
['id', 'ASC']
],
include:
[
{
model: Restaurant,
type,
include: [{
model: RestaurantType,
}
]
}
]
}).then((restaurantBranches) => {
return res.status(200).send({
message: "restaurant branches returned",
data: restaurantBranches
})
})
.catch((error) => {res.status(500).send(error.message);});
}
module.exports = {
findAll
}
//Sequelize Associations
db.RestaurantType.hasMany(db.Restaurant);
db.Restaurant.belongsTo(db.RestaurantType);
// Restaurant / Restaurant Branches
db.RestaurantBranch.belongsTo(db.Restaurant);
db.Restaurant.hasMany(db.RestaurantBranch);
Sequelize log:
Executing (default): SELECT "restaurant_branches"."id", "restaurant_branches"."name", "restaurant_branches"."description", "restaurant_branches"."email", "restaurant_branches"."phoneNumber", "restaurant_branches"."address", "restaurant_branches"."country_code", "restaurant_branches"."image", "restaurant_branches"."latitude", "restaurant_branches"."longitude", "restaurant_branches"."workingHours", "restaurant_branches"."workingDays", "restaurant_branches"."offDays", "restaurant_branches"."locationAddress", "restaurant_branches"."locationCity", "restaurant_branches"."status", "restaurant_branches"."hasParking", "restaurant_branches"."instruction", "restaurant_branches"."isActive", "restaurant_branches"."isDeleted", "restaurant_branches"."createdAt", "restaurant_branches"."updatedAt", "restaurant_branches"."restaurantId", "restaurant_branches"."cityId", "restaurant_branches"."districtId", "city"."id" AS "city.id", "city"."name" AS "city.name", "city"."code" AS "city.code", "city"."status" AS "city.status", "city"."isDeleted" AS "city.isDeleted", "city"."createdAt" AS "city.createdAt", "city"."updatedAt" AS "city.updatedAt", "city"."countryId" AS "city.countryId", "district"."id" AS "district.id", "district"."name" AS "district.name", "district"."isDeleted" AS "district.isDeleted", "district"."createdAt" AS "district.createdAt", "district"."updatedAt" AS "district.updatedAt", "district"."cityId" AS "district.cityId", "restaurant"."id" AS "restaurant.id", "restaurant"."name" AS "restaurant.name", "restaurant"."aboutUs" AS "restaurant.aboutUs", "restaurant"."phoneNumber" AS "restaurant.phoneNumber", "restaurant"."address" AS "restaurant.address", "restaurant"."latitude" AS "restaurant.latitude", "restaurant"."longitude" AS "restaurant.longitude", "restaurant"."image" AS "restaurant.image", "restaurant"."countryCode" AS "restaurant.countryCode", "restaurant"."restaurantRegisterDocument" AS "restaurant.restaurantRegisterDocument", "restaurant"."isDeleted" AS "restaurant.isDeleted", "restaurant"."createdAt" AS "restaurant.createdAt", "restaurant"."updatedAt" AS "restaurant.updatedAt", "restaurant"."restaurantTypeId" AS "restaurant.restaurantTypeId", "restaurant"."categoryId" AS "restaurant.categoryId", "restaurant"."userId" AS "restaurant.userId", "restaurant->restaurant_type"."id" AS "restaurant.restaurant_type.id", "restaurant->restaurant_type"."name" AS "restaurant.restaurant_type.name", "restaurant->restaurant_type"."photo" AS "restaurant.restaurant_type.photo", "restaurant->restaurant_type"."createdAt" AS "restaurant.restaurant_type.createdAt", "restaurant->restaurant_type"."updatedAt" AS "restaurant.restaurant_type.updatedAt" FROM "restaurant_branches" AS "restaurant_branches" LEFT OUTER JOIN "cities" AS "city" ON "restaurant_branches"."cityId" = "city"."id" LEFT OUTER JOIN "districts" AS "district" ON "restaurant_branches"."districtId" = "district"."id" LEFT OUTER JOIN "restaurants" AS "restaurant" ON "restaurant_branches"."restaurantId" = "restaurant"."id" LEFT OUTER JOIN "restaurant_types" AS "restaurant->restaurant_type" ON "restaurant"."restaurantTypeId" = "restaurant->restaurant_type"."id" ORDER BY "restaurant_branches"."id" ASC;
so far I'm doing this, and I get All the restaurant branches if I GET request to this URL:
{{URL}}/restaurant_branches?restaurantType=2
what I'd like to be getting instead is all the restaurant branches whom their restaurants belong to the restaurant type with id 2
Any help or guidance is highly appreciated.
You included where condition in include option as a type prop that's why it does not work as expected. You just need to indicate where either with your condition or as an empty object:
var where = RestaurantTypeId ? { restaurantTypeId: RestaurantTypeId } : {} ;
include:
[
{
model: Restaurant,
where,
include: [{
model: RestaurantType,
}
]
}
]
I have managed to get my include statements working with my foreign keys however when I try to add a 'where' statement to the findAll statement I am getting the below error. I have checked my foreign keys and models numerous times and I can't see any problems with them.
Do I have the syntax correct in the below API? The data in the keys is important so I don't want to have to spend more time on a workaround. I have seen other examples that have the where statement inside one of the include keys but the fields I want pulled are on the main table so I don't think this is the same situation.
Unhandled rejection Error: Include unexpected. Element has to be either a Model, an Association or an object.
API
const sequelize = require("pg");
const { Sequelize, Op, Model, DataTypes } = require("sequelize");
exports.schoolDiveLogApproval = (req, res) => {
try {
const schoolID = req.params.schoolID;
diveLog.findAll({
include: [{
model: diveType, as: 'diveTypeID_FK2',
}, {
model: diveSchool, as: 'diveSchoolID_FK',
}, {
model: current, as: 'currentID_FK',
}, {
model: visibility, as: 'visibilityID_FK',
}, {
model: user, as: 'userID_FK1',
}, {
model: diveSpot, as: 'diveSpotID_FK2'
}],
where: {
[Op.and]: [
{diveSchoolID: schoolID},
{diveVerifiedBySchool: false}
]
},
})
...........
Update
Error message
{
"message": "missing FROM-clause entry for table \"diveLog\""
}
Controller API with raw SQL
exports.schoolDiveLogApproval = async (req, res) => {
try {
const schoolID = req.params.schoolID;
const { QueryTypes } = require('sequelize');
await diveLog.sequelize.query(
'SELECT * '+
'FROM "diveLogs" '+
'LEFT OUTER JOIN "diveTypes" AS "diveTypeID_FK2" ON "diveLogs"."diveTypeID" = "diveTypeID_FK2"."diveTypeID" ' +
'LEFT OUTER JOIN "diveSchools" AS "diveSchoolID_FK" ON "diveLog"."diveSchoolID" = "diveSchoolID_FK"."diveSchoolID" ' +
'LEFT OUTER JOIN "currents" AS "currentID_FK" ON "diveLog"."currentID" = "currentID_FK"."currentID" ' +
'LEFT OUTER JOIN "visibilities" AS "visibilityID_FK" ON "diveLog"."visibilityID" = "visibilityID_FK"."visibilityID" ' +
'LEFT OUTER JOIN "userLogins" AS "userID_FK" ON "diveLog"."userID" = "userID_FK1"."userID" ' +
'LEFT OUTER JOIN "diveSpots" AS "diveSpotID_FK2" ON "diveLog"."diveSpotID" = "diveSpotFK2"."diveSpotID" ' +
'WHERE "diveLogs"."diveSchoolID" = ? ' +
'AND "diveLogs"."diveVerifiedBySchool" = ?',
{
replacements: [schoolID, false],
type: QueryTypes.SELECT
}
)
All the table and column names look correct as per the pgAdmin database so I can't see where the problem could be other than the syntax.
I have went off the way the SQL is executed in the IDE terminal so it should execute in theory. Is this more likely be to do with the way I pass the id?
Well, I've really tried some minutes around this sequelize, but I'd really suggest you to learn and use raw SQL, its way easier and universal than that.
After half an hour of trying to set up and understand this sqlize and see so many weird issues like these:
selecting non-existing columns like id, adding an "s" out of nowhere to the name of the table "user_infoS(?)".. so I gave up and came up with a query that might help you, if I understood your problem correctly.
If you send proper schema I can help you further, but yeah, sorry I can't spend more time in this sequelize, this thing is atrocious.
const { QueryTypes } = require('sequelize');
await sequelize.query(
'SELECT *'+
'FROM diveLog l'+
'JOIN diveType t ON l.diveTypeId = t.id'+
'JOIN diveSchool s ON l.diveSchoolId = s.id'+
'JOIN current c ON l.currentId = c.id'+
'JOIN visibility v ON l.visibilityId = v.id'+
'JOIN user u ON l.userId = u.id'+
'JOIN diveSpot sp ON l.diveSpotId = sp.id'+
'WHERE diveSchoolID = ?'+
'AND diveVerifiedBySchool = ?',
{
replacements: [schoolID, false],
type: QueryTypes.SELECT
}
);
With regards to the first error in your API, ensure you are requiring your models like below:
const { diveLog, diveType, diveSchool, diveSchool, current, visibility, user, diveSpot } = require('../models');
The second error message:
{
"message": "relation "divelogs" does not exist"
}
Indicates that the table "divelogs" cannot be found in your database, double check if the table exists, if it does not exist, run your migrations to create the table. Please note that, if enabled Sequelize will automatically make your table names plural. If you define a model called User, Sequelize will create the table as Users
When I went back to using the original Sequelize with the include / where clauses I removed the [Op and] from the API, then re-declared each of the models at the top of the file and it worked.
exports.schoolDiveLogApproval = async (req, res) => {
try {
const schoolID = req.params.schoolID;
diveLog.findAll({
include: [{
model: diveType, as: 'diveTypeID_FK2',
}, {
model: diveSchool, as: 'diveSchoolID_FK',
}, {
model: current, as: 'currentID_FK',
}, {
model: visibility, as: 'visibilityID_FK',
}, {
model: user, as: 'userID_FK1',
}, {
model: diveSpot, as: 'diveSpotID_FK2'
}],
where: [{
diveSchoolID: req.params.schoolID,
diveVerifiedBySchool: false
}],
})
.then((diveLog) => {
const schoolDiveLogList = [];
for (i = 0; i < diveLog.length; i++) {
Second error: you are committing a typo on aliases using sometimes "devLogS" and other times "devLoG" (in the singular).
Try more before asking here, we won't do your work for you.
I have one filter query in sequelize with dynamic where clause as below,
let ticketnotificationsWhere = {};
if (req.query.department) {
ticketnotificationsWhere.department = req.query.department;
}
if (req.query.ticketid) {
ticketnotificationsWhere.ticketid = req.query.ticketid;
}
let ticketWhere = {};
if (req.query.isactionable) {
ticketWhere.isactionable = req.query.isactionable;
}
if (req.query.maintypeid) {
ticketWhere.maintypeid = req.query.maintypeid;
}
if (req.query.typeid) {
ticketWhere.typeid = req.query.typeid;
}
if (req.query.subtypeid) {
ticketWhere.subtypeid = req.query.subtypeid;
}
let ticketdetailsWhere = {};
if (req.query.customerid) {
ticketdetailsWhere.customerid = req.query.customerid;
}
return ticketdb.ticketnotifications.findAndCountAll({
limit: req.query.pageSize,
offset: req.query.page,
where:ticketnotificationsWhere,
attributes: ['id', 'ticketid', 'createdby', 'createddate', 'status'],
include:[{
model:ticketdb.tickets,
required: true,
where:ticketWhere,
attributes: ['isactionable'],
include:[{
model:ticketdb.ticketdetails,
required: true,
where:ticketdetailsWhere,
attributes: ['poid', 'productid', 'shippingreferenceno', 'customerid', 'issueqty']
},
{
model:ticketdb.maintypemaster,
attributes: [['name', 'maintypename']]
},
{
model:ticketdb.typemaster,
attributes: [['name', 'typename']]
},
{
model:ticketdb.subtypemaster,
attributes: [['name', 'subtypename']],
},
{
model:ticketdb.ticketsource,
attributes: ['sourcename']
}]
}]
})
The problem is that only where clause of ticketnotifications goes in actual SQL where clause, rest where conditions tickets and ticketdetails goes into JOIN which is wrong. Even Limit clause is not generating. The generated sql is as below,
SELECT count("ticketnotifications"."id") AS "count" FROM
"ticketnotifications" AS "ticketnotifications" INNER JOIN "tickets" AS
"ticket" ON "ticketnotifications"."ticketid" = "ticket"."ticketid" AND
"ticket"."isactionable" = true AND "ticket"."maintypeid" = 18 AND
"ticket"."typeid" = 70 AND "ticket"."subtypeid" = 240 INNER JOIN
"ticketdetails" AS "ticket.ticketdetail" ON "ticket"."ticketid" =
"ticket.ticketdetail"."ticketid" LEFT OUTER JOIN "maintypemaster" AS
"ticket.maintypemaster" ON "ticket"."maintypeid" =
"ticket.maintypemaster"."maintypeid" LEFT OUTER JOIN "typemaster" AS
"ticket.typemaster" ON "ticket"."typeid" =
"ticket.typemaster"."typeid" LEFT OUTER JOIN "subtypemaster" AS
"ticket.subtypemaster" ON "ticket"."subtypeid" =
"ticket.subtypemaster"."subtypeid" LEFT OUTER JOIN "ticketsource" AS
"ticket.ticketsource" ON "ticket"."sourceid" =
"ticket.ticketsource"."sourceid" WHERE "ticketnotifications"."ticketid" = 123;
What I expect is
SELECT count("ticketnotifications"."id") AS "count" FROM
"ticketnotifications" AS "ticketnotifications" INNER JOIN "tickets" AS
"ticket" ON "ticketnotifications"."ticketid" = "ticket"."ticketid" INNER JOIN
"ticketdetails" AS "ticket.ticketdetail" ON "ticket"."ticketid" =
"ticket.ticketdetail"."ticketid" LEFT OUTER JOIN "maintypemaster" AS
"ticket.maintypemaster" ON "ticket"."maintypeid" =
"ticket.maintypemaster"."maintypeid" LEFT OUTER JOIN "typemaster" AS
"ticket.typemaster" ON "ticket"."typeid" =
"ticket.typemaster"."typeid" LEFT OUTER JOIN "subtypemaster" AS
"ticket.subtypemaster" ON "ticket"."subtypeid" =
"ticket.subtypemaster"."subtypeid" LEFT OUTER JOIN "ticketsource" AS
"ticket.ticketsource" ON "ticket"."sourceid" =
"ticket.ticketsource"."sourceid" WHERE "ticketnotifications"."ticketid" = 123 AND
"ticket"."isactionable" = true AND "ticket"."maintypeid" = 18 AND
"ticket"."typeid" = 70 AND "ticket"."subtypeid" = 240
LIMIT 10 OFFSET 0;
I searched a lot and got solution like setting where condition in $$ but this is for one column, I want to add/set where clause dynamically as per filters.
Any idea what I'm doing wrong?
You can you Operaters in sequelize: Operaters
so, you code can be like this:
return ticketdb.ticketnotifications.findAndCountAll({
limit: req.query.pageSize,
offset: req.query.page,
where: { [Op.and]: [{ticketId: req.query.ticketid}, {isactionable: req.query.isactionable}, {maintypeid: 18}]},
include:[{
model:ticketdb.tickets,
required: true,
where:ticketWhere,
attributes: ['isactionable'],
include:[{
model:ticketdb.ticketdetails,
required: true,
where:ticketdetailsWhere,
},
{
model:ticketdb.maintypemaster,
attributes: [['name', 'maintypename']]
},
{
model:ticketdb.typemaster,
attributes: [['name', 'typename']]
},
{
model:ticketdb.subtypemaster,
attributes: [['name', 'subtypename']],
},
{
model:ticketdb.ticketsource,
attributes: ['sourcename']
}]
}]
Hope it can help you.
Let modify it as you want to.
I'm running an into issue where Sequelize creates a subquery of the primary model and then joins the includes with that subquery instead of directly with the primary model table. The query conditions for the include(s) ends up inside the subquery's WHERE clause which makes it invalid. I have shortened names down trying to keep this compact hopefully without losing any relevant info.
Environment:
Nodejs: 6.11.3
Sequelize: 3.23.6 => Updated to 4.38.1 and problem persists
MySql: 5.7.23
Code snip models:
I.model:
models.I.hasMany(models.II);
models.I.belongsTo(models.CJ);
models.I.belongsTo(models.CJS);
II.model:
models.II.belongsTo(models.I);
CJ.model:
models.CJ.hasMany(models.I);
models.CJ.hasMany(models.CJS);
CJS.model:
models.CJS.hasMany(models.I);
Code snip query definition:
let where = { cId: '2',
iAmt: { '$gt': 0 },
'$or':
[ { '$CJ.a1$': {$like: '%246%'}} },
{ '$CJ.a2$': {$like: '%246%'} },
{ '$I.cPN$': {$like: '%246%'} }
] };
let query = {
where: where,
order: orderBy,
distinct: true,
offset: offset,
limit: limit,
include: [
{
model: CJ,
as: 'CJ',
required: false
}, {
model: CJS,
as: 'CJS',
required: false
}, {
model: II,
as: 'IIs',
required: false
}
]
};
I.findAll(query)
Produces SQL like the following:
SELECT `I`.*, `CJ`.`_id` AS `CJ._id`, `CJS`.`_id` AS `CJS._id`, `IIs`.`_id` AS `IIs._id`
FROM (SELECT `I`.`_id`, `I`.`CJId`, `I`.`CJSId`, `I`.`CId`
FROM `Is` AS `I`
WHERE `I`.`CId` = '2' AND
`I`.`iA` > 0 AND
(`CJ`.`a1` LIKE '%246%' OR
`CJ`.`a2` LIKE '%246%' OR
`I`.`cPN` LIKE '%246%'
)
ORDER BY `I`.`iNum` DESC LIMIT 0, 10) AS `I`
LEFT OUTER JOIN `CJs` AS `CJ` ON `I`.`CJId` = `CJ`.`_id`
LEFT OUTER JOIN `CJSs` AS `CJS` ON `I`.`CJSId` = `CJS`.`_id`
LEFT OUTER JOIN `IIs` AS `IIs` ON `I`.`_id` = `IIs`.`IId`
ORDER BY `I`.`iNum` DESC;
I was expecting something like this:
SELECT `I`.*, `CJ`.`_id` AS `CJ._id`, `CJS`.`_id` AS `CJS._id`, `IIs`.`_id` AS `IIs._id`
FROM `Is` AS `I`
LEFT OUTER JOIN `CJs` AS `CJ` ON `I`.`CJId` = `CJ`.`_id`
LEFT OUTER JOIN `CJSs` AS `CJS` ON `I`.`CJSId` = `CJS`.`_id`
LEFT OUTER JOIN `IIs` AS `IIs` ON `I`.`_id` = `IIs`.`IId`
WHERE `I`.`CId` = '2' AND
`I`.`iA` > 0 AND
(`CJ`.`a1` LIKE '%246%' OR
`CJ`.`a2` LIKE '%246%' OR
`I`.`cPN` LIKE '%246%'
)
ORDER BY `I`.`iNum` DESC LIMIT 0, 10
If I remove the II model from the include it does work and moves the the WHERE to the top level. I admit the structure of the query is not straight forward here, with I being a child of CJ and CJS, which in turn is a child of CJ. And then II a child of I. What am I missing here?
Bueller's or anyone's 2 cent welcome!
what happened here is because you also using order and limit together with eager loading association see the issue
to make it work, there is a little hacky solution, you need to add subQuery: false together to your root model query
let query = {
where: where,
order: orderBy,
distinct: true,
offset: offset,
limit: limit,
subQuery: false,
include: [...]
};