Ricerca nel sito web

typescript - Ordinare per colonna aggregata typeorm


Ho due tabelle: user e activity con relazione @OneToMany.

Devo scrivere una query che conti l'attività per utente e la restituisca con ordinamento disponibile. Non so come sarà ordinata, quindi devo abilitare l'ordinamento su tutti i campi, incluso activityCount.

Ho provato a fare questo con loadRelationCountAndMap qualcosa del genere

async getUsersAndCount(
    skip: number,
    limit: number,
    orderBy: string,
    orderOptions: OrderByOptions,
    query?: [string, ObjectLiteral][]
): Promise<[User[], number]> {
    const initialQuery =  this.createInitialQuery();

    if (query && query.length > 0) {
        query.forEach(q => initialQuery.andWhere(q[0], q[1]));
    }

    return await initialQuery.orderBy(orderBy, orderOptions)
        .offset(skip)
        .limit(limit)
        .printSql()
        .getManyAndCount();
}

private createInitialQuery(): SelectQueryBuilder<User> {
    return this.createQueryBuilder('user')
        .loadRelationCountAndMap('activityCount', 'user.activity', 'activityCount')
        .where('user.status = 1')
        .addGroupBy('user.id');

Ma non posso ordinare per il campo activityCount.

Poi ho provato a usare subQuery, ma non riesce a creare una query che faccia un join sulla tabella activity tramite userId.

Poi ho provato a usare una query SQL semplice così:

await this.query(
        'SELECT u."id"                AS "user_id",\n' +
        '       u."telegram_id"       AS "user_telegram_id",\n' +
        '       u."telegram_username" AS "user_telegram_username",\n' +
        '       COUNT(a.id)           AS activityCount\n' +
        'FROM "user" u\n' +
        'INNER JOIN activity a ON a."userId" = u.id\n' +
        'WHERE u."status" = 1\n' +
        'GROUP BY u."id"\n' +
        `ORDER BY $1 $2\n` +
        `OFFSET $3\n` +
        `LIMIT $4`);

con i parametri order by, direzione dell'ordine, limit e offset, ma TypeORM non ha riempito questi parametri e ho ottenuto errore di sintassi vicino a $2.

Posso concatenare le stringhe per riempire i parametri, ma questo sarà un modo davvero pessimo.

Inoltre posso risolvere questo problema usando VIEW, ma forse c'è un altro modo?