v5 api: Handle random in keyset paginate

This commit is contained in:
Arthur Jamet 2025-01-12 11:07:56 +00:00 committed by Zoe Roux
parent 67ea86a955
commit f490faa796
No known key found for this signature in database
2 changed files with 21 additions and 3 deletions

View File

@ -1,4 +1,4 @@
import { and, desc, eq, sql } from "drizzle-orm"; import { and, eq, sql } from "drizzle-orm";
import { Elysia, t } from "elysia"; import { Elysia, t } from "elysia";
import { KError } from "~/models/error"; import { KError } from "~/models/error";
import { comment } from "~/utils"; import { comment } from "~/utils";

View File

@ -1,5 +1,5 @@
import type { NonEmptyArray, Sort } from "./sort"; import type { NonEmptyArray, Sort } from "./sort";
import { eq, or, type Column, and, gt, lt, isNull } from "drizzle-orm"; import { eq, or, type Column, and, gt, lt, isNull, sql } from "drizzle-orm";
type Table<Name extends string> = Record<Name, Column>; type Table<Name extends string> = Record<Name, Column>;
@ -29,7 +29,7 @@ export const keysetPaginate = <
sort: Sort<T, Remap>; sort: Sort<T, Remap>;
}) => { }) => {
if (!after) return undefined; if (!after) return undefined;
const cursor: After = JSON.parse( let cursor: After = JSON.parse(
Buffer.from(after, "base64").toString("utf-8"), Buffer.from(after, "base64").toString("utf-8"),
); );
@ -39,6 +39,23 @@ export const keysetPaginate = <
// PERF: See https://use-the-index-luke.com/sql/partial-results/fetch-next-page#sb-equivalent-logic // PERF: See https://use-the-index-luke.com/sql/partial-results/fetch-next-page#sb-equivalent-logic
let where = undefined; let where = undefined;
let previous = undefined; let previous = undefined;
if (sort.random) {
const lastCursor = cursor.slice(-1)[0];
where = or(
where,
and(
previous,
gt(
sql`md5(${sort.random.seed} || ${table[pkSort.key]})`,
sql`md5(${sort.random.seed} || ${lastCursor})`,
),
),
);
previous = and(previous, eq(table[pkSort.key], lastCursor));
cursor = cursor.slice(1);
}
for (const [i, by] of [...sort.sort, pkSort].entries()) { for (const [i, by] of [...sort.sort, pkSort].entries()) {
const cmp = by.desc ? lt : gt; const cmp = by.desc ? lt : gt;
where = or( where = or(
@ -62,6 +79,7 @@ export const keysetPaginate = <
export const generateAfter = (cursor: any, sort: Sort<any, any>) => { export const generateAfter = (cursor: any, sort: Sort<any, any>) => {
const ret = [ const ret = [
...(sort.random ? [`random:${sort.random.seed}`] : []),
...sort.sort.map((by) => cursor[by.remmapedKey ?? by.key]), ...sort.sort.map((by) => cursor[by.remmapedKey ?? by.key]),
cursor.pk, cursor.pk,
]; ];