NestJS 类型标注
严格打字的 TypeORM 寄存器或查询构建器的配置辅助器方法
安装
$ yarn add @appotter/nestjs-typeorm-paginate
或者说
$ npm i --save @appotter/nestjs-typeorm-paginate
请使用@appotter/nestjs-typeorm-pagnation^3 关于打字机,请使用@appotter/nestjs-打字机-pagnation^4.0.0
使用量
服务
仓库
import { Injectable } from '@nestjs/common';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { CatEntity } from './entities';
import {
paginate,
Pagination,
IPaginationOptions,
} from '@appotter/nestjs-typeorm-paginate';
@Injectable()
export class CatService {
constructor(
@InjectRepository(CatEntity)
private readonly repository: Repository<CatEntity>,
) {}
async paginate(options: IPaginationOptions): Promise<Pagination<CatEntity>> {
return paginate<CatEntity>(this.repository, options);
}
}
查询构建器
import { Injectable } from '@nestjs/common';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { CatEntity } from './entities';
import {
paginate,
Pagination,
IPaginationOptions,
} from '@appotter/nestjs-typeorm-paginate';
@Injectable()
export class CatService {
constructor(
@InjectRepository(CatEntity)
private readonly repository: Repository<CatEntity>,
) {}
async paginate(options: IPaginationOptions): Promise<Pagination<CatEntity>> {
const queryBuilder = this.repository.createQueryBuilder('c');
queryBuilder.orderBy('c.name', 'DESC'); // Or whatever you need to do
return paginate<CatEntity>(queryBuilder, options);
}
}
主计长
import { Controller, DefaultValuePipe, Get, ParseIntPipe, Query } from '@nestjs/common';
import { CatService } from './cat.service';
import { CatEntity } from './cat.entity';
import { Pagination } from '@appotter/nestjs-typeorm-paginate';
@Controller('cats')
export class CatsController {
constructor(private readonly catService: CatService) {}
@Get('')
async index(
@Query('page', new DefaultValuePipe(1), ParseIntPipe) page: number = 1,
@Query('limit', new DefaultValuePipe(10), ParseIntPipe) limit: number = 10,
): Promise<Pagination<CatEntity>> {
limit = limit > 100 ? 100 : limit;
return this.catService.paginate({
page,
limit,
route: 'http://cats.com/cats',
});
}
}
如果您使用
ParseIntPipe在查询参数(如示例)上,不要忘记添加DefaultValuePipe。见 问题517 需要更多信息.
页:1
routepagnation 选项的属性也可以是绝对路径的短版本/cats改为http://cats.com/cats
示例答复
{
"items": [
{
"lives": 9,
"type": "tabby",
"name": "Bobby"
},
{
"lives": 2,
"type": "Ginger",
"name": "Garfield"
},
{
"lives": 6,
"type": "Black",
"name": "Witch's mate"
},
{
"lives": 7,
"type": "Purssian Grey",
"name": "Alisdaya"
},
{
"lives": 1,
"type": "Alistair",
"name": "ali"
},
...
],
"meta": {
"itemCount": 10,
"totalItems": 20,
"itemsPerPage": 10,
"totalPages": 5,
"currentPage": 2
},
"links" : {
"first": "http://cats.com/cats?limit=10",
"previous": "http://cats.com/cats?page=1&limit=10",
"next": "http://cats.com/cats?page=3&limit=10",
"last": "http://cats.com/cats?page=5&limit=10"
}
}
items: 某个实体的数组
meta.itemCount: 项数组的长度(即本页上项的数量)
meta.totalItems: 匹配过滤条件的某个实体的总量
meta.itemsPerPage: 每页要求的项目(即 limit 参数)
meta.totalPages页: 1 limit(中文(简体) )
meta.currentPage: 当前页此piginator"点"到
links.first: 第一个调用 QQ 的 URL "" (blank) 如果没有 route 定义
links.previous: 上页调用QQ的 URL "" (blank) 如果没有先前呼叫
links.next: 下一页调用QQ的URL "" (空白) 如果没有页面调用
links.last: 最后一个调用QQ的 URL "" (blank) 如果没有 route 定义
请注意
links.first可能没有定义“ page” 查询参数
查找参数
@Injectable()
export class CatService {
constructor(
@InjectRepository(CatEntity)
private readonly repository: Repository<CatEntity>,
) {}
async paginate(options: IPaginationOptions): Promise<Pagination<CatEntity>> {
return paginate<CatEntity>(this.repository, options, {
lives: 9,
});
}
}
Eager 装入
Eager加载应该和打字机的急切财产一起工作 像这样
import { Entity, OneToMany } from 'typeorm';
@Entity()
export class CatEntity {
@OneToMany(t => TigerKingEntity, tigerKing.cats, {
eager: true,
})
tigerKings: TigerKingEntity[];
}
// service
class CatService {
constructor(private readonly repository: Repository<CatEntity>) {}
async paginate(page: number, limit: number): Promise<Pagination<CatEntity>> {
return paginate(this.repository, { page, limit });
}
}
查询构建器
然而,在使用查询构建器时,您必须亲自给实体水分. 这是过去我用过的一个粗略的例子。 这不妙,但这是部分 类型ORM会做的.
const results = paginate(queryBuilder, { page, limit });
return new Pagination(
await Promise.all(
results.items.map(async (item: SomeEntity) => {
const hydrate = await this.someRepository.findByEntity(item);
item.hydrated = hydrate;
return item;
}),
),
results.meta,
results.links,
);
原始查询
const queryBuilder = this.repository
.createQueryBuilder<{ type: string; totalLives: string }>('c')
.select('c.type', 'type')
.addSelect('SUM(c.lives)', 'totalLives')
.groupBy('c.type')
.orderBy('c.type', 'DESC'); // Or whatever you need to do
return paginateRaw(queryBuilder, options);
原始和实体
TypeORM 使用类似的方法 getRawAndEntities
让我们假设有一个结合的桌子,使每只猫与它的猫玩具相匹配. 我们要给每只猫带来多少玩具.
const queryBuilder = this.repository
.createQueryBuilder<{ type: string; totalLives: string }>('cat')
.leftJoinAndSelect('cat.toys', 'toys')
.addSelect('COUNT(toys)::INTEGER', 'toyCount')
.groupBy('cat.name');
这样我们就能得到 被捕捉的猫的信息 加上额外的原始查询 来构建我们的实际反应值. 返回的 pagination 对象会是相同的,但现在可以处理或映射结果和所需的原始对象.
const [pagination, rawResults] = await paginateRawAndEntities(query, options);
pagination.items.map((item, index) => {
// we can do what we need with the items and raw results here
// change your items using rawResults.find(raw => raw.id === item.id)
});
return pagination;
关于合并表格和原始值的说明
由于原始结果的值将包含所有被询问的合并表格项目,所以您必须确保按您使用时的需要处理这些项目。 参考 TypeORM 软件 获取Raw和实体 视需要执行.
原始的Results阵列会看起来像这样:
[
{ // Bobby appears 3 times due to the joined query
"cat_lives": 9,
"cat_type": "tabby",
"cat_name": "Bobby",
"toyCount": 3
},
{
"cat_lives": 9,
"cat_type": "tabby",
"cat_name": "Bobby",
"toyCount": 3
},
{
"cat_lives": 9,
"cat_type": "tabby",
"cat_name": "Bobby",
"toyCount": 3
},
{
"cat_lives": 2,
"cat_type": "Ginger",
"cat_name": "Garfield",
"toyCount": 1
},
...
]
自定义元数据变压器
如果您想要更改从页形对象返回的元数据 。 那就用那个 metaTransformer 在这样的选项中
class CustomPaginationMeta {
constructor(
public readonly count: number,
public readonly total: number,
) {}
}
return paginate<MyEntity, CustomPaginationMeta>(this.repository, {
page,
limit,
metaTransformer: (meta: IPaginationMeta): CustomPaginationMeta => new CustomPaginationMeta(
meta.itemCount,
meta.totalItems,
),
});
这将导致上述返回 CustomPaginationMeta 输入 meta 属性而不是默认 IPaginationMeta。 。 。 .
自定义链接查询参数标签
如果你想改变 limit 和(或) page 元链接中的标签,然后使用 routingLabels 在这样的选项中
return paginate<MyEntity>(this.repository, {
page,
limit,
routingLabels: {
limitLabel: 'page-size', // default: limit
pageLabel: 'current-page', //default: page
}
});
这将导致链接像 http://example.com/something?current-page=1&page-size=3。 。 。 .