将原始 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);
});
}
使用 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);
});
}