node.js - 如何在 nodejs pg 模块中创建动态查询功能?
问题描述
例如:
const update = ({title, price, imageUrl, description, whereId, whereTitle }) => {
return db.query(
`UPDATE products
SET title=$1,
price=$2,
"imageUrl"=$3,
description=$4
WHERE
id=$5,
title ILIKE '%$6%'
`,
[title, price, imageUrl, description, whereId, whereTitle],
)
}
update({
whereId: 1,
title: 'Aliens 2: Electric Boogaloo',
description: 'Best sequel ever',
})
// shall execute this query:
// UPDATE products SET title='Aliens 2: Electric Boogaloo', description'Best sequel ever' WHERE id=1
// and keeping the price, "imageUrl" untouched / previous value
update({
whereTitle: 'godfather',
price: 20,
})
// shall execute this query:
// UPDATE products SET price=20 WHERE title ILIKE '%godfather%'
// or set the price of every products that contain the word 'godfather' as $20
// and keeping the title, "imageUrl", description, id untouched / previous value
现在,我必须为每个可能的查询创建一个查询
设置标题在哪里 id
SET 标题,价格 WHERE id
SET price, "imageUrl" WHERE title
...
这不是很干,因此我认为必须有更好的方法
编辑1:
这就是我想象的代码的样子。
db.query(
`UPDATE products
SET
title !== null? "title=$1," : skipToNextLine()
price !== null? "price=$2," : skipToNextLine()
"imageUrl" !== null? "\"imageUrl\"=$3," : skipToNextLine()
description !== null? "description=$4" : skipToNextLine()
whereId !== null && whereTitle !== null? "WHERE" : skipToNextLine()
whereId !== null? "id=$5," : skipToNextLine()
whereTitle !== null? "title ILIKE '%$6%'" : skipToNextLine()
`,
[title, price, imageUrl, description, whereId, whereTitle],
)
我以三元表达的风格来做,但还有很多其他的风格。我认为这个想法类似于pug.js,ejs,handlebars等html的模板语言。除了为您的html编写几十个静态html文件之外,还有其他方法。
编辑2:
我使用字符串连接来实现快速而肮脏的解决方案,但我想知道它是否容易受到 SQL 注入的影响。代码也变得很长,代码可靠性/易理解性显着下降。
这是我目前的解决方案:
const update = ({
title,
price,
imageUrl,
description,
whereId,
whereTitle,
}) => {
let queryText = 'UPDATE products SET'
let queryValue = []
let dollarCounter = 1
if (!!title) {
queryText = queryText.concat(` title=$${dollarCounter},`)
queryValue.push(title)
dollarCounter++
}
if (!!price) {
queryText = queryText.concat(` price=$${dollarCounter},`)
queryValue.push(price)
dollarCounter++
}
if (!!imageUrl) {
queryText = queryText.concat(` "imageUrl"=$${dollarCounter},`)
queryValue.push(imageUrl)
dollarCounter++
}
if (!!description) {
queryText = queryText.concat(` description=$${dollarCounter},`)
queryValue.push(description)
dollarCounter++
}
queryText = queryText.slice(0, -1)
if (!!whereId || !!whereTitle) queryText = queryText.concat(' WHERE')
if (!!whereId) {
queryText = queryText.concat(` id=$${dollarCounter},`)
queryValue.push(whereId)
dollarCounter++
}
if (!!whereTitle) {
queryText = queryText.concat(` title ILIKE '%$${dollarCounter}%',`)
queryValue.push(whereTitle)
dollarCounter++
}
queryText = queryText.slice(0, -1)
const query = {
name: 'update',
text: queryText,
values: queryValue,
}
return db.query(query)
}
解决方案
推荐阅读
- java - Android 应用程序未在 Android Studio 中的 Marshmallow android 版本中打开
- azure - 在使用 Ansible 配置 azure vm 时安装软件
- mongodb - 将现有文档字段添加到聚合输出
- javascript - 如何从接口外部访问变量
- reactjs - 需要在circle ci中配置Springboot和react app
- rest - 有没有办法通过 api 在 Azure 数据目录中注册数据资产而无需用户登录?
- python - 如何从元组列表和另一个数据框构建数据框?
- android - 在我的应用程序中使用指纹默认硬件 android 登录,与(paytm money 和 Gpay、imobile、axis bank)相同
- java - 在事务结束时执行复杂的逻辑
- python - 使用熊猫创建列后如何将“列”添加回txt文件?