如何对搜索结果进行分页?
How to paginate searched results?
如何使用游标对搜索结果进行分页?
这是我查询数据的功能,有问题,因为当我加载更多数据时,有些项目与搜索查询无关?
@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,
};
}
嘿,我一直在使用这个很酷的包来分页 table 检查一下 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);
您可以使用自定义系统,而不是安装可能存在漏洞的繁重软件包。
这是一个示例 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
个元素。
非常感谢您的回复,但我能够使用查找选项自行解决,
@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,
};
}
如何使用游标对搜索结果进行分页?
这是我查询数据的功能,有问题,因为当我加载更多数据时,有些项目与搜索查询无关?
@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,
};
}
嘿,我一直在使用这个很酷的包来分页 table 检查一下 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);
您可以使用自定义系统,而不是安装可能存在漏洞的繁重软件包。
这是一个示例 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
个元素。
非常感谢您的回复,但我能够使用查找选项自行解决,
@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,
};
}