Vyhledávání na webu

databáze - Jak filtrovat a počítat položky vztahu v TypeORM?


V mém projektu mám službu pro oznámení událostí. Entity vypadají takto.

@Entity('event')
class Event {
    @Column()
    message: string;

    @Column()
    readAt: Date;

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

@Entity('user')
class User {
    @PrimaryGeneratedColumn()
    id: string;

    @Column()
    email: string;

    @Column()
    fullName: string;

    @OneToMany(() => Event, event => event.user)
    events: Event[];

    unread: number;
}

Třídy User a Event jsou entity s relacemi jeden-ku-mnohým, jak můžete vidět v deklaraci entity, a fungují správně s databází PostgreSQL.

Musím najít všechny uživatelské objekty s počtem jejich nepřečtených událostí.

Prozatím toho dosahuji tím, že najdu všechny uživatele s jejich událostmi a ručně spočítám nepřečtené události pomocí pole readAt v entitě události.

Takto:

...
const users = await this.userRepository.find({ relations: ['events'] });

users.forEach(user => {
   user.unread = user.events.reduce((cnt, event) => {
      if (event.readAt) { return cnt + 1; }
      return cnt;
   }, 0);
);
...

Vím, že je to špatná praxe, a jsem si docela jistý, že toho mohu dosáhnout pomocí funkcí TypeOrm, ne ručním počítáním.

Jediné, co mohu udělat, je filtrování nepřečtených zpráv v objektech uživatelů.

...
constructor(@InjectRepository(User) private userRepository: Repository<User>) { }
...
const found = await this.usersRepository.createQueryBuilder('user')
   .leftJoinAndSelect('user.events', 'events')
   .where('events.readAt is null')
   .getMany();
...

Ale i toto má své omezení. Uživatelské objekty bez nezpracovaných událostí nejsou tímto dotazem vráceny.

Každá pomoc bude oceněna.

Aplikace je vytvořena pomocí frameworku NestJs a celý kód je napsán v TypeScriptu.

Děkuji předem.

Odpověď č. 1

Zkuste :

const found = await this.usersRepository.createQueryBuilder('user')
   .loadRelationCountAndMap('user.unreadEventCount', 'user.events', 'event', (qb) => qb.where('event.readAt IS NULL'))
   .getMany();

O loadRelationCountAndMap:

Prvým argumentem je název vlastnosti, ke které bude počet přiřazen - to by bylo pole na vaší entitě, které NENÍ @Column.

Druhé je název vztahu

3. je alias, který se má použít s dotazem

Čtvrtý je volitelný QueryBuilder pro další filtrování, ve vašem případě kontroluje, zda je sloupec readAt nulový

Související články