Knex Raw Select 带变量的 Postgresql
Knex Raw Select Postgresql with variable
我可以在 knex 查询中使用变量吗? db.raw(select usr_vote.vote where usr_vote.user.id = ${loggedInUserId}
) 有什么问题?其他一切正常。
在现在不工作的 db.raw 中,我正在尝试使用变量 (loggedInUserId) 来获取 logged-in 用户对问题的投票历史记录(他们可以投票赞成/反对,所以值为 -1 或 1 或 null)。在此先感谢您的帮助!
有 4 个表如下所示:
askify_users
- 编号
- user_name
askify_questions
- id
- 标题
- body
- 标签
- date_created
- user_id(FK 引用 askify_users.id)
askify_answers
- id
- 回答
- question_id(FK 引用 askify_question.id)
- user_id(FK 引用 askify_users.id)
askify_question_votes
- 列表项
- question_id(FK 引用 askify_questions.id)
- user_id(FK 引用 askify_users.id)
- 投票(-1 或 1)
- 主键(question_id、user_id)
getAllQuestions(db, loggedInUserId) {
return db
.from('askify_questions AS q')
.select(
'q.id AS question_id',
'q.title AS question_title',
'q.body AS question_body',
'q.date_created AS date_created',
'q.tags',
db.raw(
`count(DISTINCT ans) AS number_of_answers`
),
db.raw(
`SUM(DISTINCT usr_vote.vote) AS sum_of_votes`
),
db.raw(
`select usr_vote.vote where usr_vote.user_id = ${loggedInUserId}`
),
db.raw(
`json_strip_nulls(
json_build_object(
'user_id', usr.id,
'user_name', usr.user_name,
'full_name', usr.full_name,
'date_created', usr.date_created
)
) AS "user"`
)
)
.leftJoin(
'askify_answers AS ans',
'q.id',
'ans.question_id'
)
.leftJoin(
'askify_users AS usr',
'q.user_id',
'usr.id'
)
.leftJoin(
'askify_question_vote AS usr_vote',
'q.id',
'usr_vote.question_id'
)
.groupBy('q.id', 'usr.id')
},
查询应如下所示。除了 'user_vote_history' 以外的所有东西都在工作。
serializeQuestion(question) {
const { user } = question
return {
id: question.question_id,
question_title: xss(question.question_title),
question_body: xss(question.question_body),
date_created: new Date(question.date_created),
number_of_answers: Number(question.number_of_answers) || 0,
user_vote_history: question.user_vote_history,
sum_of_votes: Number(question.sum_of_votes),
tags: xss(question.tags),
user: {
user_id: user.user_id,
user_name: user.user_name,
full_name: user.full_name,
user_vote: user.user_vote,
date_created: new Date(user.date_created)
},
}
},
我注意到 @felixmosh 在这里关于绑定值是正确的,但只是为了详细说明:这里的关键是 字符串替换发生时 。如果你这样做:
db.raw(`SELECT vote WHERE user_id = ${loggedInUserId}`)
只要 JS 解释器到达这一行,就会在 JavaScript 中进行替换。数据库引擎与 loggedInUserId
中的内容无关,Knex 也与此无关:您实际上是在绕过所有内置保护。
稍微好点的是:
db.raw("SELECT vote WHERE user_id = ?", loggedInUserId)
这允许 Knex 转义 loggedInUserId
中的字符串。如果您愿意,可以使用命名绑定:
db.raw("SELECT vote WHERE user_id = :loggedInUserId", { loggedInUserId })
但是,使用 Knex 已经为子查询提供的工具可以轻松避免所有这些与绑定有关的麻烦:只需将子查询放在一个函数中。
db
.from("askify_questions AS q")
.select(
"q.id AS question_id",
qb => qb.select("usr_vote.vote").where({ user_id: loggedInUserId })
)
.leftJoin(
"askify_question_vote AS usr_vote",
"q.id",
"usr_vote.question_id"
);
qb
参数代表 "query builder",由 Knex 传递给您的函数。它的行为非常像您的 db
对象。
这会生成 SQL 类似于:
SELECT
"q"."id" AS "question_id",
(
SELECT "usr_vote"."user_id" WHERE "user_id" = ?
)
FROM "askify_questions AS q"
LEFT JOIN "askify_question_vote" AS "usr_vote"
ON "q"."id" = "usr_vote"."question_id"
我可以在 knex 查询中使用变量吗? db.raw(select usr_vote.vote where usr_vote.user.id = ${loggedInUserId}
) 有什么问题?其他一切正常。
在现在不工作的 db.raw 中,我正在尝试使用变量 (loggedInUserId) 来获取 logged-in 用户对问题的投票历史记录(他们可以投票赞成/反对,所以值为 -1 或 1 或 null)。在此先感谢您的帮助!
有 4 个表如下所示:
askify_users
- 编号
- user_name
askify_questions
- id
- 标题
- body
- 标签
- date_created
- user_id(FK 引用 askify_users.id)
askify_answers
- id
- 回答
- question_id(FK 引用 askify_question.id)
- user_id(FK 引用 askify_users.id)
askify_question_votes
- 列表项
- question_id(FK 引用 askify_questions.id)
- user_id(FK 引用 askify_users.id)
- 投票(-1 或 1)
- 主键(question_id、user_id)
getAllQuestions(db, loggedInUserId) {
return db
.from('askify_questions AS q')
.select(
'q.id AS question_id',
'q.title AS question_title',
'q.body AS question_body',
'q.date_created AS date_created',
'q.tags',
db.raw(
`count(DISTINCT ans) AS number_of_answers`
),
db.raw(
`SUM(DISTINCT usr_vote.vote) AS sum_of_votes`
),
db.raw(
`select usr_vote.vote where usr_vote.user_id = ${loggedInUserId}`
),
db.raw(
`json_strip_nulls(
json_build_object(
'user_id', usr.id,
'user_name', usr.user_name,
'full_name', usr.full_name,
'date_created', usr.date_created
)
) AS "user"`
)
)
.leftJoin(
'askify_answers AS ans',
'q.id',
'ans.question_id'
)
.leftJoin(
'askify_users AS usr',
'q.user_id',
'usr.id'
)
.leftJoin(
'askify_question_vote AS usr_vote',
'q.id',
'usr_vote.question_id'
)
.groupBy('q.id', 'usr.id')
},
查询应如下所示。除了 'user_vote_history' 以外的所有东西都在工作。
serializeQuestion(question) {
const { user } = question
return {
id: question.question_id,
question_title: xss(question.question_title),
question_body: xss(question.question_body),
date_created: new Date(question.date_created),
number_of_answers: Number(question.number_of_answers) || 0,
user_vote_history: question.user_vote_history,
sum_of_votes: Number(question.sum_of_votes),
tags: xss(question.tags),
user: {
user_id: user.user_id,
user_name: user.user_name,
full_name: user.full_name,
user_vote: user.user_vote,
date_created: new Date(user.date_created)
},
}
},
我注意到 @felixmosh 在这里关于绑定值是正确的,但只是为了详细说明:这里的关键是 字符串替换发生时 。如果你这样做:
db.raw(`SELECT vote WHERE user_id = ${loggedInUserId}`)
只要 JS 解释器到达这一行,就会在 JavaScript 中进行替换。数据库引擎与 loggedInUserId
中的内容无关,Knex 也与此无关:您实际上是在绕过所有内置保护。
稍微好点的是:
db.raw("SELECT vote WHERE user_id = ?", loggedInUserId)
这允许 Knex 转义 loggedInUserId
中的字符串。如果您愿意,可以使用命名绑定:
db.raw("SELECT vote WHERE user_id = :loggedInUserId", { loggedInUserId })
但是,使用 Knex 已经为子查询提供的工具可以轻松避免所有这些与绑定有关的麻烦:只需将子查询放在一个函数中。
db
.from("askify_questions AS q")
.select(
"q.id AS question_id",
qb => qb.select("usr_vote.vote").where({ user_id: loggedInUserId })
)
.leftJoin(
"askify_question_vote AS usr_vote",
"q.id",
"usr_vote.question_id"
);
qb
参数代表 "query builder",由 Knex 传递给您的函数。它的行为非常像您的 db
对象。
这会生成 SQL 类似于:
SELECT
"q"."id" AS "question_id",
(
SELECT "usr_vote"."user_id" WHERE "user_id" = ?
)
FROM "askify_questions AS q"
LEFT JOIN "askify_question_vote" AS "usr_vote"
ON "q"."id" = "usr_vote"."question_id"