web-dev-qa-db-ja.com

ライタムの関係項目をフィルタリングしてカウントする方法

プロジェクトにイベント通知サービスがあります。エンティティはこのように見えます。


@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;
}
 _

クラス、UserおよびEventは、エンティティ宣言で見て、PostgreSQLデータベースで正しく機能しているとおりに、1対多の関係を持つエンティティです。

未読イベント数を持つすべてのユーザーオブジェクトを見つける必要があります。

今のところ、イベントエンティティ内のreadAtフィールドを使用して、そのイベントを使用してすべてのユーザーを検索し、未読イベントを手動でカウントすることでこれを実現しています。

このような:

...
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);
);
...
 _

私はこれが悪い練習であることを知っています、そして、私は手動カウントではなく、Typeormの機能を使ってこれを達成できることをよく確信しています。

私ができる唯一のものは、ユーザーオブジェクト内の未読メッセージをフィルタリングすることです。

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

しかし、これもその制限を持っています。未読イベントなしのユーザーオブジェクトは、このクエリによって返されません。

どんな助けにも感謝されるでしょう。

アプリはNESTJSフレームワークで作られ、すべてのコードはTypeScriptで書かれています。

前もって感謝します。

6
triaton

試す:

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

loadRelationCountAndMapについて:

1引数は、カウントがマッピングされるプロパティ名です - それは@Columnではないエンティティ上のフィールドになります。

2ndは関係名前です

3RDはクエリで使用するエイリアスです

4thは、さらにフィルタリングするオプションのQueryBuilder、readAt _列がnullの場合にチェックしている

1
piotr.jura