Closed2
Prismaでランダムにレコード取得したい人生だった
まだ(20230410)無理ぽそう
skipは使えないのか?
要は1つ飛ばしみたいなことがまだできないのでskipでは要件に満たない
例えば a, b, c, d, ..., z
に対して skip: 3, take: 3
とかでクエリ発行すると d, e, f
が返ってくる
欲しいのは d, m, z
みたいな感じ
方法
- 素のSQL書く
- 乱数でsort対象のキーを指定する
- 複数回GETする
『乱数でsort対象のキーを指定する』について
async pickRandom(count: number): Promise<CognitiveTest[]>{
const itemCount = await this.prisma.cognitiveTest.count();
const skip = Math.max(0, Math.floor(Math.random() * itemCount) - count);
const orderBy = randomPick(['id', 'field1', 'field2']);
const orderDir = randomPick([SortOrder.asc, SortOrder.desc]);
return this.prisma.cognitiveTest.findMany({
take: count,
skip: skip,
orderBy: { [orderBy]: orderDir },
});
}
これで都度異なるキーによってソートされるため、一応ランダムな感じにはなる
ただ、キーごとのソートに差異がない場合はランダムなキーでのソートはあまり意味ない
複数回GETする
フロントで何回もfetchするんでもバックエンドでAPI叩きまくるんでもいいけど、仮に9個ランダムなレコードを取得する場合、
// frontで行う
for (let i = 0; i < 9; i++) {
await fetch(URL)
}
// backで行う
const totalCount = await prisma.sample.count()
const args = {/* ... */}
const random = []
for (let i = 0; i < 9; i++) {
const sample = await prisma.sample.findFirst(args)
if (sample) {
random.push(sample)
args.skip = Math.floor(Math.random() * totalCount)
}
}
SSRとかだと取得回数によってはだいぶ難ありそうだけどrevalidateが大きいSGとかなら複数回DB叩いても悪影響なさそうではある
参考
このスクラップは2023/04/10にクローズされました