Search code examples
typeorm

Explain typeorm join syntax


I'm new to TypeOrm and I'm trying to use an inner join, but the documentation doesn't explain it, so I have an example:

import {Entity, PrimaryGeneratedColumn, Column, OneToMany} from "typeorm";
import {Photo} from "./Photo";

@Entity()
export class User {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    name: string;

    @OneToMany(type => Photo, photo => photo.user)
    photos: Photo[];
}

import {Entity, PrimaryGeneratedColumn, Column, ManyToOne} from "typeorm";
import {User} from "./User";

@Entity()
export class Photo {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    url: string;

    @ManyToOne(type => User, user => user.photos)
    user: User;
}

If you want to use INNER JOIN instead of LEFT JOIN just use innerJoinAndSelect instead:

const user = await createQueryBuilder("user")
    .innerJoinAndSelect("user.photos", "photo", "photo.isRemoved = :isRemoved", { isRemoved: false })
    .where("user.name = :name", { name: "Timber" })
    .getOne();

This will generate:

SELECT user.*, photo.* FROM users user
    INNER JOIN photos photo ON photo.user = user.id AND photo.isRemoved = FALSE
    WHERE user.name = 'Timber'

Can somebody explain to me in more detail how it functions? For example, I don't know what the first("user") refers to, I mean, is it a column? How does it change if I need to use it between columns? Also, what is the explanation for innerJoinAndSelect, why does it have 3 values, how are the values defined in TypeORM syntax? When it is using :name and after {name: "Timber"}, that object is defining :name?, and at last what happens if I don't want to get only one and I want to get all the information from table1 where matches with table2, because actually that is what I want to do.


Solution

  • For the First question the param of createQueryBuilder which is user in your case, it's the alias you use in your query:

    SELECT user., photo. FROM users user INNER JOIN photos photo ON photo.user = user.id AND photo.isRemoved = FALSE WHERE user.name = 'Timber'

    const user = await createQueryBuilder("user") .innerJoinAndSelect("user.photos", "photo", "photo.isRemoved = :isRemoved", { isRemoved: false }) .where("user.name = :name", { name: "Timber" }) .getOne();

    The second question:The first argument is the relation you want to load, the second argument is an alias you assign to this relation's table and the third one is optional for any condition you'd add

    the forth question, you should use getMany() instead of getOne();

    I didn't understand the third question.