Skip to content

$Dto.query/DtoQueryBase

$Dto.query/DtoQueryBase用于标注 Query 参数

DtoQueryBase的用法

1. 创建DTO

在 VSCode 中,可以通过右键菜单Vona Create/Dto创建 DTO 的代码骨架:

typescript
@Dto()
export class DtoOrderQuery {}

2. 继承DtoQueryBase

typescript
@Dto()
export class DtoOrderQuery extends DtoQueryBase {}

DtoQueryBase成员字段

由于DtoOrderQuery继承自DtoQueryBase,因此,有以下成员字段:

名称说明举例
columns要查询的字段清单*, id,orderNo,remark, ["id","orderNo","remark"]
where条件语句{ "orderNo": { "_include_": "order001" } }
orders排序orderNo,desc, [["orderNo", "desc"], ["createdAt", "desc"]]

标注Query参数

仍以 Controller Order 的 findAll 方法为例,标注 Query 参数:

diff
+ import type { IQueryParams } from 'vona-module-a-orm';
+ import { Arg } from 'vona-module-a-web';

class ControllerOrder extends BeanBase {
  @Web.get('findAll')
  @Api.body(v.array(DtoOrderResult))
  async findAll(
+   @Arg.queryPro(DtoOrderQuery) params: IQueryParams<ModelOrder>,
  ): Promise<DtoOrderResult[]> {
    return this.scope.model.order.select(params);
  }
}
  • @Arg.queryPro:此 Pipe 对 Query 参数进行 transform,需要传入参数DtoOrderQuery
  • IQueryParams: Pipe 对 Query 参数进行 transform 后的数据类型为IQueryParams,需要传入泛型参数ModelOrder,从而与model.order.select方法的参数类型相匹配

基于DtoOrderQuery生成的 Swagger/Openapi 效果如下:

$Dto.query

如果需要在 DTO 中添加业务字段的查询条件,可以使用$Dto.query

diff
@Dto()
export class DtoOrderQuery
+ extends $Dto.query(EntityOrder, ['orderNo', 'remark']) {}
  • $Dto.query:自动从EntityOrder中提取字段orderNo/remark,然后与DtoQueryBase成员字段进行合并

基于DtoOrderQuery生成的 Swagger/Openapi 效果如下:

添加自定义字段

还可以直接在 DTO 中添加自定义字段

diff
@Dto()
export class DtoOrderQuery
+ extends $Dto.query(EntityOrder, ['remark']) {
+ @Api.field(v.optional())
+ orderNo?: string;
}
  • EntityOrder中自动提取字段remark
  • 添加自定义字段orderNo

Openapi参数

我们还可以指定 Openapi 参数,从而支持更多能力

1. Relations

比如,Model Order 与 Model User 是n:1的关系,我们可以在 Query 参数中传入userName作为查询条件。那么,需要在 DTO 中添加userName字段,并且设置 Openapi 参数

typescript
@Dto()
export class DtoOrderQuery
  extends $Dto.query(EntityOrder, ['orderNo', 'remark']) {
  @Api.field(v.optional(), v.openapi({
    query: {
      table: $tableName(EntityUser),
      joinType: 'innerJoin',
      joinOn: ['userId', 'testVonaUser.id'],
      originalName: 'name',
    },
  }))
  userName?: string;
}
名称说明
table关联表名
joinType关联类型,默认为innerJoin
joinOn关联条件
originalName原始字段名

基于DtoOrderQuery生成的 Swagger/Openapi 效果如下:

2. 基于relations的orders

当 Model Order 与 Model User 进行联合查询时,orders中的字段如果在两个数据表中都存在,那么就必须明确指定表名前缀。比如:testVonaOrder.createdAt,desc

Vona ORM 内置了基于 relations 的 orders 处理逻辑,只需要在 DTO 中设置 Openapi 参数即可:

diff
@Dto<IDtoOptionsOrderQuery>({
+ openapi: {
+   query: {
+     table: $tableName(EntityOrder),
+   },
+ },
})
export class DtoOrderQuery
  extends $Dto.query(EntityOrder, ['orderNo', 'remark']) {
  @Api.field(v.optional(), v.openapi({
    query: {
      table: $tableName(EntityUser),
      joinType: 'innerJoin',
      joinOn: ['userId', 'testVonaUser.id'],
      originalName: 'name',
    },
  }))
  userName?: string;
}

自定义Query Transform

对于自定义字段,Vona ORM 提供了内置的 Transform 规则。比如:

  • orderNo是 string 类型,系统自动转换为条件语句'orderNo': { _includesI_: 'some input' }
  • userName也是 string 类型,系统自动转换为条件语句'name': { _includesI_: 'some input' }

为了支持更复杂的业务需求,可以提供自定义 Query Transform

1. 约定名称

比如,我们在 Controller Order 的findAll方法中使用 Query。那么,只需在当前 Controller 中提供findAllQueryTransform即可

diff
@Controller
class ControllerOrder {
+  findAllQueryTransform(_info: IPipeOptionsQueryTransformInfo): boolean | undefined {
+    return undefined;
+  }

  @Web.get('findAll')
  @Api.body(v.array(DtoOrderResult))
  async findAll(
    @Arg.queryPro(DtoOrderQuery) params: IQueryParams<ModelOrder>,
  ): Promise<DtoOrderResult[]> {
    return this.scope.model.order.select(params);
  }
}

如果需要将userName转换为条件语句'name': 'some input',那么代码如下:

typescript
class ControllerOrder {
  findAllQueryTransform(info: IPipeOptionsQueryTransformInfo): boolean | undefined {
    if (info.key === 'userName') {
      info.params.where[info.fullName] = info.value;
      return true;
    }
    return undefined;
  }
}

2. Query Transform返回值

Query Transform 返回值如下:

名称说明
true提供了自定义逻辑,忽略系统内置规则
false没有提供自定义逻辑,忽略系统内置规则
undefined没有提供自定义逻辑,使用系统内置规则

2. 自定义名称

我们也可以为Query Transform提供自定义名称,比如:myCustomQueryTransform

diff
class ControllerOrder {
+ myCustomQueryTransform(info: IPipeOptionsQueryTransformInfo): boolean | undefined {
+   if (info.key === 'userName') {
+     info.params.where[info.fullName] = info.value;
+     return true;
+   }
+   return undefined;
+ }

  @Web.get('findAll')
  @Api.body(v.array(DtoOrderResult))
  async findAll(
+   @Arg.queryPro(DtoOrderQuery, 'myCustomQueryTransform') params: IQueryParams<ModelOrder>,
  ): Promise<DtoOrderResult[]> {
    return this.scope.model.order.select(params);
  }
}
  • @Arg.queryPro:此 Pipe 对 Query 参数进行 transform,传入参数'myCustomQueryTransform'

3. 自定义函数

也可以直接提供自定义函数:

diff
+ function myCustomQueryTransform(_ctx: VonaContext, info: IPipeOptionsQueryTransformInfo): boolean | undefined {
+   if (info.key === 'userName') {
+     info.params.where[info.fullName] = info.value;
+     return true;
+   }
+   return undefined;
+ }

class ControllerOrder {
  @Web.get('findAll')
  @Api.body(v.array(DtoOrderResult))
  async findAll(
+   @Arg.queryPro(DtoOrderQuery, myCustomQueryTransform) params: IQueryParams<ModelOrder>,
  ): Promise<DtoOrderResult[]> {
    return this.scope.model.order.select(params);
  }
}

基于 MIT 许可发布