Question: Joins and querying off those joins with related data
See original GitHub issueI have a model with related data, and I’m attempting to do a query based on the related data and I’m having issues.
I have a Street model, which has multiple Property models attached.
I basically want to do:
select p.*, s.* from Property as p
inner join Street as s
on s.id = p.street_id
where p.name = 'propName' and s.name = 'streetName'
The problem I’m running into is that propName is not unique, and can exist on multiple streets, and may or may not exist on a particular street.
I attempted to do the following:
Property.forge({name: 'propName'}.fetch( {
withRelated: [
{
'street': function(qb) {
qb.where('name', 'streetName');
}
}
]
}
The problem with that is the initial query is run as
select * from Property where name = 'propName'
which sometimes returns data, and then another query is run to load the related data.
select * from Streets where id = 1 and name = 'streetName'
The second query returns in my case returns no data, so I now get the wrong Property model with an empty Street object. As a work around, I check for a populated related Street before returning the Property model, but this feels inefficient.
Is this intended behavior, or is there options on fetch I’m missing here? I would prefer not to have to drop to raw knex to build my join statement and where clause, and it would be great if Bookshelf could handle this scenario as a single query.
Any help is appreciated, thanks!
Issue Analytics
- State:
- Created 10 years ago
- Comments:17 (6 by maintainers)
This would be a really helpful feature.
I have a table with Organizations, and another table with Users (super simplified diagram below)
I’d like to be able to search “john” and find companies with the primary contact being John Smith, or find a company called “John’s Auto Body”.
@vongohren The thing is that all relations except
belongsToMany
and.trough
don’t make use ofJOIN
s, but rather separateSELECT
queries for each table involved. That is a design decision to reduce the amount of data that comes out of the database, at the expense of producing one extra query for each table. Maybe you could start by analyzing if this rationale makes sense or if it’s perfectly fine to useJOIN
performance wise.Another difficulty is the interface. How will this feature work and how will it be exposed to users? It shouldn’t be necessary to use
.query()
, or to know how SQL works. It should all be done on the Bookshelf side ideally.The relations and eager loading code isn’t all that complicated, but it is a bit spread out through different files (
lib/relation.js
,lib/eager.js
,lib/base/relation.js
,lib/base/eager.js
). However, the test suite is quite extensive and should help you detect any regressions quickly.