这个排序有两个问题
来源:5-9 支持不同的排序规则
init_center
2024-05-24
第一个问题是分页时使用 create_at 字段作为 cursor 条件,老师现在的代码是不管 asc 还是 desc,where 的 sql 都固定为小于:
sql`("files"."created_at", "files"."id") < (${new Date(cursor.createdAt).toISOString()}, ${cursor.id})`
但在 asc 时应该改为大于才符合预期:
sql`("files"."created_at", "files"."id") > (${new Date(cursor.createdAt).toISOString()}, ${cursor.id})`
第二个问题是 ISO 时间不包含微秒,但是postgresql 中的时间是包含微秒的,直接把 ISO 时间和数据库中的时间进行判断会导致出现问题,也就是 ISO 时间把微秒信息给丢失了,导致同一条数据的 ISO 时间会比数据库中的时间要小,每次分页查询时使用 cursor 的 create_at 作为判断条件,因为对于 cursor 这条数据来说数据库中的 "files"."created_at" 要比 new Date(cursor.createdAt).toISOString() 要大,所以下一页中依然会有上一页的最后一条数据,导致数据重复,并且当滚动到最后一条数据时,一直滚动会一直返回最后一条数据,永远都滚不完。
针对以上两个问题,我将代码改为:
const result = await db
.select()
.from(files)
.limit(limit)
.where(
cursor
? orderBy.field === "createdAt" && orderBy.order === "asc"
? sql`(DATE_TRUNC('milliseconds',"files"."created_at"), "files"."id") > (${new Date(
cursor.createdAt
).toISOString()}, ${cursor.id})`
: sql`(DATE_TRUNC('milliseconds',"files"."created_at"), "files"."id") < (${new Date(
cursor.createdAt
).toISOString()}, ${cursor.id})`
: undefined
)
.orderBy(
orderBy.order === "desc"
? desc(files[orderBy.field])
: asc(files[orderBy.field])
);
修改后目前看起来没问题,但是不知道有没有更好更简洁的方案。
写回答
1回答
-
init_center
提问者
2024-06-11
已解决
10
相似问题