将原始 select 语句添加到 Knex 查询构建器

Adding a raw select statement to the Knex query builder

使用 Knex 查询我的 Postgres 数据库。我有一个使用 Knex QueryBuilder 提供 "base" 查询的函数。这工作正常,直到我需要向 SELECT 语句添加一些原始内容。据我所知,运行 .raw 总是想要 return 结果。不过,我只需要将它添加到 QueryBuilder,这样它就可以由我的应用程序的不同部分执行。

const baseQuery = knex
    .select(newUserFields)
    .from('users')
    .leftJoin('user_roles', 'users.id', 'user_roles.user_id')
    .leftJoin('roles', 'user_roles.role_id', 'roles.id')
    .leftJoin('role_permissions', 'roles.id', 'role_permissions.role_id')
    .leftJoin(
        'permissions',
        'permissions.id',
        'role_permissions.permission_id'
    )
    .groupBy(
        'users.id',
        'users.email',
        'users.name',
        'users.status',
        'users.created_at',
        'users.password_reset_expiration',
        'users.password',
        'users.password_reset_token'
    )
    .orderBy('users.created_at', 'desc');

我需要将以下内容添加到 select:

knex.raw('to_json(array_agg(distinct roles.name)) as roleNames')
knex.raw('to_json(array_agg(distinct permissions.name)) as permissionNames')

如何将这些原始 select 添加到基本查询中,以便随后可以将基本查询作为 QueryBuilder 传递给不同的函数并添加到?

knex 的酷之处在于它是一个 queryBuilder,它允许您调用方法而不受 顺序的任何限制来电。这意味着您可以在函数中构建基本查询,然后附加其他内容(例如其他列)。

在你的情况下,你可以再打电话给 select(knex 将加入 select 电话)

// base-query.js
export const getBaseQuery = () => knex
  .select(newUserFields)
  .from('users')
  .leftJoin('user_roles', 'users.id', 'user_roles.user_id')
  .leftJoin('roles', 'user_roles.role_id', 'roles.id')
  .leftJoin('role_permissions', 'roles.id', 'role_permissions.role_id')
  .leftJoin('permissions', 'permissions.id', 'role_permissions.permission_id')
  .groupBy(
    'users.id',
    'users.email',
    'users.name',
    'users.status',
    'users.created_at',
    'users.password_reset_expiration',
    'users.password',
    'users.password_reset_token'
  )
  .orderBy('users.created_at', 'desc');

// other-file.js
import {getBaseQuery} from 'base-query';

const enhancedQuery = getBaseQuery().select([
  knex.raw('to_json(array_agg(distinct roles.name)) as roleNames'),
  knex.raw('to_json(array_agg(distinct permissions.name)) as permissionNames'),
]);

const results = await enhancedQuery;

我大量使用的另一种很酷的方法解决了以下需求:有时我需要从外部更改内部查询,我使用 modify 例如,我有一个 getProducts 方法,它执行 select 查询并进行一些数据转换。 为了实现 getProductById 需要 return 相同的数据结构 (只需要过滤基本查询)我传递了一个 queryModifier 方法来修改原始查询。


async function getProducts(queryModifier) {
  const products = await knex
    .select('*')
    .from('products')
    .modify((queryBuilder) => {
      if (typeof queryModifier === 'function') {
        return queryModifier(queryBuilder);
      }
    });

  return products.map(someDataTransformation);
}

async function getProductById(id) {
  return getProducts((qb) => {
    return qb.where('id', id);
  });
}