向Knex查询构建器添加原始选择语句

时间:2020-06-11 20:34:10

标签: node.js postgresql knex.js

使用Knex对我的Postgres数据库进行查询。我有一个使用Knex QueryBuilder提供“基本”查询的函数。在我需要向SELECT语句中添加原始内容之前,此方法可以正常工作。据我所知,运行.raw总是要返回结果。不过,我只需要将其添加到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');

我需要在选择项中添加以下内容:

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

如何将这些原始选择添加到基本查询中,然后可以将基本查询作为QueryBuilder传递给其他函数并添加到其中?

1 个答案:

答案 0 :(得分:1)

关于knex的一件很酷的事情是它是一个 queryBuilder ,它使您可以调用方法而不受调用顺序的任何限制。这意味着您可以只在函数中构造基本查询,然后将附加的内容(例如附加的列)附加到该查询上。

根据您的情况,您可以再打一次电话来选择(knex将加入选择呼叫)

// 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,它需要返回相同的数据结构(只需要过滤基本查询),我传递了一个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);
  });
}