typeorm: Lazy loading with eager loading in combination doesn't work

Issue type:

[ ] question [x] bug report [ ] feature request [ ] documentation issue

Database system/driver:

[ ] cordova [ ] mongodb [ ] mssql [x] mysql / mariadb [ ] oracle [ ] postgres [ ] sqlite [ ] sqljs [ ] react-native

TypeORM version:

[ ] latest [ ] @next [x] 0.2.5 (or put your version here)

Steps to reproduce or a small repository showing the problem:

Giving the below entities;

class User extends BaseEntity{
    @OneToMany(type => Reservation, reservation => reservation.client)
    reservations: Promise<Reservation[]>;
}

class Reservation extends BaseEntity{
    @ManyToOne(type => Hotel, hotel => hotel.reservations, {eager: true})
    hotel: Hotel;

    @ManyToOne(type => User, user => user.reservations, {eager: true})
    user: User;
}

class Hotel extends BaseEntity{
    @OneToMany(type => Reservation, reservation => reservation.hotel)
    reservations: Promise<Reservation[]>;
}

Doing User.find(1).reservations returns a list of reservations but without any eagerly loaded relations(for Hotel and User).

I know there is some redundancy because the User under the Reservation is the same, but what I really want are the hotels (and if I request using some hotel, like hotel.reservations what I really I want are the users. But it’s ok if there is some redundancy)

Doing Reservation.find(1) returns the expected result.

  1. Is this intended behavior?
  2. How can I get the expected result without manually getting every reservation and then load their relationships? Like:
let user = User.find(1).
let reservations = users.reservations;
reservations.forEach((reservation)=>{
    reservation.user...// load the relations somehow using query builder???.  this is really messy
    ....
})

The Reservation.find(1) works just fine and User.find(1).reservations should also.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 13
  • Comments: 16 (4 by maintainers)

Most upvoted comments

Using lazy relations for this purpose is a bad idea. Really, really better to contribute into ORM and add needed features 😆

I am trying to get rid of the query builder as much as possible and use Active Record for simple queries like this. Why? I want the code to be simpler, more readable and easier to understand. The query builder looks redundant for these types of queries. Yes, it is OK for complex queries but for this I find it not needed.

For example this query:

const userId = await getRepository(User)
    .createQueryBuilder("user")
    .select("user.id")
    .where("user.id = :id", { id: 1 })
    .getRawOne();
// here, the word user is written 4 times

It would be nice to just write:

const photosSums = User.where('id',1).getRawOne('id')
// the `.where` will create a query parameter automatically

or

const users = await getRepository(User)
    .createQueryBuilder("user")
    .leftJoinAndSelect("user.photos", "photo")
    .where("user.group = :id", { id: 1 })
    .where("photo.album = :album", { album: 3 })
    .getMany();

Can be written like this maybe?:

const users = User
    .where('group',1) // get users that have the column group = 1
    .with({
        'photos': photo => photo.where('album',3) // eager loaded. `photo` is a query builder. here we have the full power of a query builder
    })
    .getMany()
// the `.with` for example will get the relationships. the `photo` argument is a query builder maybe?

I am just borrowing syntax from Laravel’s Eloquent ORM. It just an idea to make it work easier with Active Record as I said in #2285.

It would be really nice to have an explanation of why this isn’t supported (and why it seems to be considered a bad idea) here. Also, the docs should probably mention that this doesn’t work.

In particular, since the error message you get when you try to make both sides of a relation eager actually suggests mixing eager and lazy:

Error: Circular eager relations are disallowed. A#bs contains "eager: true", and its inverse side B#a contains "eager: true" as well. Remove "eager: true" from one side of the relation.

@johannespfeiffer I didn’t solve it. Sorry 😦