如何对搜索结果进行分页?
Posted
技术标签:
【中文标题】如何对搜索结果进行分页?【英文标题】:How to paginate searched results? 【发布时间】:2021-05-22 08:21:42 【问题描述】:如何使用光标对搜索结果进行分页?
这是我的数据查询功能,有问题,因为当我加载更多数据时,有些项目与搜索的查询无关?
@UseMiddleware(isAuthenticated)
@Query(() => PaginatedQuizzes)
async quizzes(
@Arg('limit', () => Int) limit: number,
@Arg('cursor', () => String, nullable: true ) cursor: string | null,
@Arg('query', () => String, nullable: true ) query: string | null
): Promise<PaginatedQuizzes>
const realLimit = Math.min(50, limit);
const realLimitPlusOne = realLimit + 1;
const qs = await getConnection()
.getRepository(Quiz)
.createQueryBuilder('q')
.leftJoinAndSelect('q.author', 'author')
.leftJoinAndSelect('q.questions', 'questions')
if (query)
const formattedQuery = query.trim().replace(/ /g, ' <-> ');
qs.where(
`to_tsvector('simple',q.title) @@ to_tsquery('simple', :query)`,
query: `$formattedQuery:*`,
).orWhere(
`to_tsvector('simple',q.description) @@ to_tsquery('simple', :query)`,
query: `$formattedQuery:*`,
);
if (cursor)
qs.where('q."created_at" < :cursor',
cursor: new Date(parseInt(cursor)),
);
const quizzes = await qs
.orderBy('q.created_at', 'DESC')
.take(realLimitPlusOne)
.getMany();
return
quizzes: (quizzes as [Quiz]).slice(0, realLimit),
hasMore: (quizzes as [Quiz]).length === realLimitPlusOne,
;
【问题讨论】:
【参考方案1】:您可以使用自定义系统,而不是安装可能存在漏洞的繁重软件包。
这是一个示例controller
,带有limit
和page
参数,用于在x
页面上获取n
元素
@Get('elements/:limit/:page')
getElementsWithPagination(
@Param('limit') limit: number,
@Param('page') page: number,
): Promise<ElementsEntity[]>
return this.elementsService.getElementsWithPagination(limit, page);
这是访问您的存储库的service
async getElementsWithPagination(
limit: number,
page: number,
): Promise<ElementsEntity[]>
return this.elementsRepository.findElementsWithPagination(limit, page);
最后是带有查询参数的repository
,从最新到最旧排序
async findElementsWithPagination(limit, page): Promise<ElementsEntity[]>
return this.find(
take: limit,
skip: limit * (page - 1),
order: createdAt: 'DESC' ,
);
借助这个系统,您可以逐页查询n
元素。
【讨论】:
大型结果集怎么样?在丢弃skip指定的行数之前,不采取并跳过将整个结果集加载到内存中吗?如果您有多个 10k 行的结果集怎么办?【参考方案2】:嘿,我一直在使用这个很酷的包对表格进行分页检查here
import buildPaginator from 'typeorm-cursor-pagination';
const paginator = buildPaginator(
entity: User,
paginationKeys: ['id'],
query:
limit: 10,
order: 'ASC',
,
);
const data, cursor = await paginator.paginate(queryBuilder);
【讨论】:
【参考方案3】:非常感谢您的回复,但我可以使用 find 选项自行解决,
@UseMiddleware(isAuthenticated)
@Query(() => PaginatedQuizzes)
async quizzes(
@Arg('limit', () => Int) limit: number,
@Arg('cursor', () => String, nullable: true ) cursor: string | null,
@Arg('query', () => String, nullable: true ) query: string | null
): Promise<PaginatedQuizzes>
const realLimit = Math.min(20, limit);
const realLimitPlusOne = realLimit + 1;
let findOptionInitial: FindManyOptions =
relations: [
'author',
'questions',
],
order:
created_at: 'DESC',
,
take: realLimitPlusOne,
;
let findOption: FindManyOptions;
if (cursor && query)
const formattedQuery = query.trim().replace(/ /g, ' <-> ');
findOption =
...findOptionInitial,
where: [
description: Raw(
(description) =>
`to_tsvector('simple', $description) @@ to_tsquery('simple', :query)`,
query: formattedQuery,
),
created_at: LessThan(new Date(parseInt(cursor))),
,
title: Raw(
(title) =>
`to_tsvector('simple', $title) @@ to_tsquery('simple', :query)`,
query: formattedQuery,
),
created_at: LessThan(new Date(parseInt(cursor))),
,
],
;
else if (cursor)
findOption =
...findOptionInitial,
where:
created_at: LessThan(new Date(parseInt(cursor))),
,
;
else if (query)
const formattedQuery = query.trim().replace(/ /g, ' <-> ');
findOption =
...findOptionInitial,
where: [
description: Raw(
(description) =>
`to_tsvector('simple', $description) @@ to_tsquery('simple', :query)`,
query: formattedQuery,
),
,
title: Raw(
(title) =>
`to_tsvector('simple', $title) @@ to_tsquery('simple', :query)`,
query: formattedQuery,
),
,
],
;
else
findOption = findOptionInitial;
const quizzes = await Quiz.find(findOption as FindManyOptions);
return
quizzes: (quizzes as [Quiz]).slice(0, realLimit),
hasMore: (quizzes as [Quiz]).length === realLimitPlusOne,
;
【讨论】:
以上是关于如何对搜索结果进行分页?的主要内容,如果未能解决你的问题,请参考以下文章
我们如何使用 Flask 对 SQL Server 搜索结果进行分页
如何使用 Laravel 和 jQuery 对查询结果进行分页
如何在 Reactive Extensions 中组合两个 observables 以对结果进行分页?
如何在 MongoDB 中对聚合查询结果进行分页并获得总文档数(Node.js + Mongoose)?