首页 > 解决方案 > 使用 knex.js 和 TypeScript 构建基于条件的查询

问题描述

我想构建一个查询,根据是否传递了名称和/或城市,它应该添加一个where子句。

我在文档中没有找到执行此操作的特定方法,因此我尝试在查询中附加where方法,但可能无法指定类型。

let query: Knex.QueryBuilder = await knex<Member>('members')

if (name) {
  query = query.where('name', String(name))
}

if (city) {
  query = query.where('city', String(city))
}

const members: Member[] = query.select('*')

TypeError: query.select is not a function

此外,TypeScript 警告:

让查询

Type 'Member[]' is missing the following properties from type 'QueryBuilder<any, any>': client, or, not, and, and 118 more.

常量成员

Type 'QueryBuilder<any, DeferredKeySelection<any, string, false, {}, false, {}, never> | DeferredKeySelection<any, string, false, {}, false, {}, never>[]>' is missing the following properties from type 'Member[]': length, pop, push, concat, and 25 more.

标签: typescriptknex.js

解决方案


Knex.js 有一个伪造的then实现,它在调用时会在数据库上执行查询。

因此,您只需将await(然后调用)移动到最后一部分。

它应该如下所示:

let query: Knex.QueryBuilder = knex<Member>('members');
// ---------------------------^

if (name) {
  query = query.where('name', String(name));
}

if (city) {
  query = query.where('city', String(city));
}

const members: Member[] = await query.select('*');

一个更好看的结构将使用modify.

const members: Member[] = await knex<Member>('members')
  .select('*')
  .modify((queryBuilder) => {
    if (name) {
      queryBuilder.where('name', String(name));
    }

    if (city) {
      queryBuilder.where('city', String(city));
    }

    return queryBuilder;
  });

推荐阅读