概要
いちいちnodes, totalCount, hasNextPageとか書くのめんどくさいから
ジェネリクス使って汎用的に使えるようにしてみた
ベストプラクティスじゃないと思うので参考までに見てください!
こんな風にかける
const query = {};
query['id'] = productsInput.id;
query['name'] = Like(`%${name}%`);
const paginationQuery = new PaginationQuery<User>(
query,
this.userRepository, // Repository<User>
limit,
offset,
['posts', 'posts.comments'], // entityのリレーションも取得したいならここも書く
);
paginationQuery.setOrderCond({ updatedAt: 'DESC' }); // 任意
const result = await paginationQuery.run();
コード
import {
FindConditions,
JoinOptions,
ObjectLiteral,
Repository,
} from 'typeorm';
import { EntityFieldsNames } from 'typeorm/common/EntityFieldsNames';
export class PaginationQuery<T> {
private query:
| string
| ObjectLiteral
| FindConditions<T>
| FindConditions<T>[];
private limit: number;
private offset: number;
private relations: string[];
private repository: Repository<T>;
private order: { [P in EntityFieldsNames<T>]?: 'DESC' | 'ASC' | 1 | -1 };
private join: JoinOptions;
constructor(
query: string | ObjectLiteral | FindConditions<T> | FindConditions<T>[],
repository: Repository<T>,
limit?: number,
offset?: number,
relations?: string[],
) {
this.query = query;
this.limit = limit || 10;
this.offset = offset || 0;
this.relations = relations || [];
this.repository = repository;
}
async setOrderCond(
order: { [P in EntityFieldsNames<T>]?: 'DESC' | 'ASC' | 1 | -1 },
) {
this.order = order;
}
async setJoinCond(join: JoinOptions) {
this.join = join;
}
async run() {
const [data, total] = await this.repository.findAndCount({
where: this.query,
take: this.limit,
skip: this.offset,
relations: this.relations,
order: this.order,
join: this.join,
});
let hasNextPage = true;
if (data.length !== this.limit || total - (this.offset + this.limit) <= 0)
hasNextPage = false;
return {
nodes: data,
totalCount: total,
hasNextPage: hasNextPage,
};
}
}
捕捉
Q. なんでorderとjoinはセッター使ってるの?
A.
[P in EntityFieldsNames<T>]
こいつが問題児
例えば、createAt: "DESC"って書きたいんだけど上記の型エラーが出ちゃう
Tの中にcreateAtなんてないやんけ!的なやつ
なので、インスタンス生成してからセッタ経由でやったらうまくいったって話
まとめ
この辺りはtypeorm側で用意してくれたら嬉しいな〜っていうのと
joinしてからのリレーション先のカラムをwhereで使いたい時が上手くいかない
この辺りはうまい方法あったら教えて欲しいです