New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Query with nested include and custom join condition #1869
Comments
Querying on the through model/join table is not possible currently unfortuneatly. |
I tried querying associations with conditions and it worked: User.findAll({include: [{model: Post, where: {active: true}}] INNER JOIN `posts` AS `post` ON `users`.`id` = `post`.`user_id` AND `post`.`active`=true Shouldn't this be closed? |
@lucaswxp the issue is about filtering on join table models - You example is just filtering on the target model :) |
+1 I'm having the same issue. It's would be nice to have this feature. |
@lvarayut what does your code look like? It's possible to ammend the join conditions with |
@mickhansen I want to join two tables using SELECT * FROM InterviewSummaries as summary JOIN UserProfiles as profile ON
(summary.StudentId = profile.id AND summary.version = profile.version) |
@lvarayut i see
Perhaps an API like: include: [{model: UserProfile, where: {summary: {$field: UserProfile.rawAttributes.version}}] |
Perhaps you could already do it like: include: [{model: UserProfile, where: {summary: sequelize.literal('profile.version')}}] |
Thanks @mickhansen for your quick response. I'ill try it soon. :) |
Is querying on the through model/join table now possible with version 3.*? |
@eclipse1985 Yes |
Oh thanks, from which version exactly? |
2.0 rc8 appearently :) https://github.com/sequelize/sequelize/blob/master/changelog.md#200-rc8 |
Ok, it works. But if I has 1:N relationships like:
and I want to find this item doing:
it returns only a part of original object, something like
without other color values... There is a way to handle this? |
@eclipse1985 Please provide some more context - models, assocations and actual find calls |
@eclipse1985 I think I know what you mean - this is happening because when you are using condition in include then only rows matching that condition will be joined (only Red colors). Instead you have to first filter parent model (select all parent models that have at least one color with value = "red") and then for each bucket join (include) all colors that belong to it (include WITHOUT condition) var Sequelize = require('sequelize')
var sequelize = new Sequelize('postgres://postgres:postgres@localhost/sequelize_test')
var Bucket = sequelize.define('Bucket', {
name: { type: Sequelize.TEXT, allowNull: false }
})
var Color = sequelize.define('Color', {
value: { type: Sequelize.TEXT, allowNull: false }
})
Bucket.hasMany(Color, { as: 'colors', foreignKey: 'BucketId' })
Color.belongsTo(Bucket, { as: 'bucket', foreignKey: 'BucketId' })
sequelize.sync({ force: true }).then(function(){
return Bucket.create({ name: 'myBucket' })
}).then(function(bucket){
var colors = ['red', 'geen', 'blue'].map(function(color){
return { value: color, BucketId: bucket.id }
})
return Color.bulkCreate(colors)
}).then(function(){
return Bucket.find({
where: {
// here you can use custom subquery to select only buckets that has AT LEAST one "red" color
$and: [['EXISTS( SELECT * FROM "Colors" WHERE value = ? AND "BucketId" = "Bucket".id )', 'red']]
},
include: [
// and then join all colors for each bucket that meets previous requirement ("at least one...")
{ model: Color, as: 'colors' }
]
})
}).then(function(bucket){
console.log(JSON.stringify(bucket, null, 2)) // output
}) output: {
"id": 1,
"name": "myBucket",
"createdAt": "2015-09-14T17:38:49.817Z",
"updatedAt": "2015-09-14T17:38:49.817Z",
"colors": [
{
"id": 1,
"value": "red",
"createdAt": "2015-09-14T17:38:49.824Z",
"updatedAt": "2015-09-14T17:38:49.824Z",
"BucketId": 1
},
{
"id": 2,
"value": "geen",
"createdAt": "2015-09-14T17:38:49.824Z",
"updatedAt": "2015-09-14T17:38:49.824Z",
"BucketId": 1
},
{
"id": 3,
"value": "blue",
"createdAt": "2015-09-14T17:38:49.824Z",
"updatedAt": "2015-09-14T17:38:49.824Z",
"BucketId": 1
}
]
} This "technique" is quite good for Postgres because Bucket.find({
where: {
// subquery that will select all buckets that have color "red"
id: { $in: Sequelize.literal('(SELECT DISTINCT "BucketId" FROM "Colors" WHERE value = \'red\')') }
},
include: [
// select all colors per each bucket
{ model: Color, as: 'colors' }
]
})
Edited example: |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If this is still an issue, just leave a comment 🙂 |
Is there a way to do this in the latest version, 4.2.1? It seems, "Support for literal replacements in the |
I know is not the best solution, but I have solved a similar issue with this implementation:
This is with sequelize 4.4.2, I don't know if it is working in previous versions. |
@janmeier Thanks. 'through' and 'required: true' helped me. associate:
This worked for me |
why doesn't this work?
and instead of all kinds of messy nested JS code to make mess SQL code... 1 JOIN, 2 WHEREs no subqueries easily stacked with
...this lib constantly makes me do all kinds of extra loops and object manipulation, strange native static methods AND/OR raw queries. |
nice suggestion, @jeremybradbury, if you dont like it you are free to use a different one or create your own lib.. |
@cesar2064 I know i bitch a lot but I really do appreciate this lib. I was actually in the midst of doing exactly what you suggested before finding Sequelize and moving to it in a time crunch. but right now reporting is all done in raw queries and filtering is becoming mind-numbing. I am in the middle of building function to format queries like the above into something to filter related tables with. I'll come back with something useful in the next day or so even it uses raws. |
i ended up building a raw filter query of just ids... dynamically adding joins and where sections depending on the object passed in into an array of ids then passed it into the original query like this:
where now my brain hurts |
I have four tables join by belongsTo relationship. location belongs to city, city belongs to state and state belongs to country. when i search for a location by id and wish to get city, state and country in the response then I include these model in nested include format like the following. router.get('/getLocation/:id',function(req,res){ And the response I am getting is like the following { How can I get the response as following { |
@jacinto123 Were you able to get a fix? |
I was able to get around this by using this query instead
|
what to do with this case ? ` SELECT a.idListing,a.listingtitle,a.listingImage,c.name FROM listing a LEFT JOIN listingcategory b ON a.listingCategory = b.idListingCategory LEFT JOIN offercateogry c ON JSON_CONTAINS(a.offercategory, CAST(c.idofferCateogry as JSON), '$'); ` |
I had the same issue and I was able to fix it with.
What I did here is to run a subquery that get all the workflow id that meets the necessary conditions in the Action table(It's a one to many table).If the condition is met in one of the many data, I select the Id and then use the main query to generate the necessary data base on those workflowid selected from the Actions table. |
I am using master.
I prepared gist with 3 files:
.js
is actual test,.json
is json output from test and.sql
is SQL generated by Sequelize that makes sequelize to produce invalid result.https://gist.github.com/alekbarszczewski/e66cbb99f95debf1e4ce
Basically what I want is:
Unfortunately it does not work (you can see in gist) because my custom join query (
EXISTS(...)
) is applied to wrong JOIN table. Joins are as follows:Is it possible to apply custom join condition to
PlaylistsPosts
in this query?Maybe there is other workaround?
I guess I could do something like:
But then I would get result in wrong format -> each playlist would have playlistsPosts and then each playlistsPost would have post attribute...
The text was updated successfully, but these errors were encountered: