首页 > 解决方案 > 如何在使用 Typescript 和 TypeORM 的查询中使用可选顺序参数

问题描述

我正在使用最新版本的 Graphql、Typescript、type-graphql 和 TypeORM。我设置了基本的 CRUD,现在想添加功能以选择性地对查询的输出进行排序以获取所有产品。

这是我正在处理的功能。目前我硬编码它按名称按升序排序,效果很好。但我想让属性和排序方向依赖于用户输入,我在排序界面中定义。当我尝试使用排序参数(例如sorting.parameter)时出现以下错误

No overload matches this call.
  Overload 1 of 2, '(this: ObjectType<Product>, options?: FindManyOptions<Product> | undefined): Promise<Product[]>', gave the following error.
    Type '{ sorting: string; }' is not assignable to type '{ name?: "ASC" | "DESC" | 1 | -1 | undefined; id?: "ASC" | "DESC" | 1 | -1 | undefined; tags?: "ASC" | "DESC" | 1 | -1 | undefined; createdAt?: "ASC" | "DESC" | 1 | -1 | undefined; }'.
      Object literal may only specify known properties, and 'sorting' does not exist in type '{ name?: "ASC" | "DESC" | 1 | -1 | undefined; id?: "ASC" | "DESC" | 1 | -1 | undefined; tags?: "ASC" | "DESC" | 1 | -1 | undefined; createdAt?: "ASC" | "DESC" | 1 | -1 | undefined; }'.
  Overload 2 of 2, '(this: ObjectType<Product>, conditions?: FindConditions<Product> | undefined): Promise<Product[]>', gave the following error.
    Argument of type '{ order: { sorting: string; }; }' is not assignable to parameter of type 'FindConditions<Product>'.
      Object literal may only specify known properties, and 'order' does not exist in type 'FindConditions<Product>'.
import { Service } from 'typedi';
import { Product } from '../entity/Product';
import { CreateProductInput, UpdateProductInput } from '../../schema/products';

interface Sorting {
  parameter: "name" | "created_at",
  direction: "ASC" | "DESC"
}

@Service()
export class ProductService {
  getAll = async (sorting? : Sorting): Promise<Product[]> => {
    if (sorting) {
// tried using ({order: {sorting.parameter : sorting.direction}});
      return Product.find({order: {name : "ASC"}});
    }
    return Product.find();
  };
.
.
.
}

产品实体定义如下:

import {
    Entity,
    PrimaryGeneratedColumn,
    Column,
    BaseEntity,
    CreateDateColumn,
  } from 'typeorm';

//   import {Tag} from './Tag'
  
  @Entity()
  export class Product extends BaseEntity {
    @PrimaryGeneratedColumn()
    id!: number;
  
    @Column()
    name!: string;
  
    // @OneToMany(type => Tag, tag => tag.name)
    // @Column({ type: () => [Tag]})
    @Column({ type: 'text', array: true })
    tags!: string[];
  
    @CreateDateColumn({ name: 'created_at' })
    createdAt!: Date;
  }

我的解析器看起来像这样。

import { Query, Resolver, Mutation, Arg } from 'type-graphql';
import { Service } from 'typedi';
import { Product, CreateProductInput, UpdateProductInput } from '../schema/products';
import { ProductService } from '../database/services/productService';

@Service()
@Resolver(() => Product)
export class ProductResolver {
  constructor(private readonly productService: ProductService) {}

  @Query(() => [Product], { nullable: true })
  async getProducts(
    @Arg('sorting', {nullable: true})  inputParameter: "name" | "created_at",
    @Arg('direction', {nullable: true, defaultValue: "ASC"}) inputDirection: "ASC" | "DESC"): Promise<Product[]> {
    return this.productService.getAll({parameter: inputParameter, direction: inputDirection});
  }

标签: typescriptgraphqltypeormtypegraphql

解决方案


我使它与这个一起工作:

getAll = async (sorting? : Sorting): Promise<Product[]> => {
    if (sorting?.parameter === "createdAt") {
      return Product.find({order: {createdAt : sorting.direction}});
    } else if (sorting?.parameter === "name") {
      return Product.find({order: {name : sorting.direction}});
    }
    return Product.find();
  };

因此,我将我期望的 2 个潜在属性拆分为 if 子句,而不是访问一次 sort.properties。有点难看,因为每当有变化时我都必须对其进行调整,但我不确定这种设置是否可以避免。

问题是我试图将“someKey”设置为以下格式的字符串:Product.find(order: {someKey: someValue}),但它只接受我实体的键


推荐阅读