diff --git a/api/src/controllers/movies.ts b/api/src/controllers/movies.ts index a4922a72..34928261 100644 --- a/api/src/controllers/movies.ts +++ b/api/src/controllers/movies.ts @@ -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 { KError } from "~/models/error"; import { comment } from "~/utils"; diff --git a/api/src/models/utils/keyset-paginate.ts b/api/src/models/utils/keyset-paginate.ts index 29aa14ba..76714dce 100644 --- a/api/src/models/utils/keyset-paginate.ts +++ b/api/src/models/utils/keyset-paginate.ts @@ -1,5 +1,5 @@ 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 = Record; @@ -29,7 +29,7 @@ export const keysetPaginate = < sort: Sort; }) => { if (!after) return undefined; - const cursor: After = JSON.parse( + let cursor: After = JSON.parse( 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 let where = 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()) { const cmp = by.desc ? lt : gt; where = or( @@ -62,6 +79,7 @@ export const keysetPaginate = < export const generateAfter = (cursor: any, sort: Sort) => { const ret = [ + ...(sort.random ? [`random:${sort.random.seed}`] : []), ...sort.sort.map((by) => cursor[by.remmapedKey ?? by.key]), cursor.pk, ];