Node.js ES6异步/等待、ExpressJS和Postgres事务 修订问题
我修改了这个问题,希望得到更清楚的答案Node.js ES6异步/等待、ExpressJS和Postgres事务 修订问题,node.js,postgresql,async-await,node-postgres,Node.js,Postgresql,Async Await,Node Postgres,我修改了这个问题,希望得到更清楚的答案 我试图根据传入的req.body和表中的现有数据,在ExpressJS中处理数据 我收到一个req.body,其中包含一个更新字段的JSON列表。其中一些字段在Postgres中存储为JSONB。如果传入字段是JSONB,则发出请求的表单(外部代码)已经运行了jsonpatch.compare(),以生成修补程序列表,传入的是这些修补程序,而不是完整的值。对于任何非JSONB值,传入值只需要传递到UPDATE查询 我有一个工作版本,如下所示,它假装表中现
我试图根据传入的
req.body
和表中的现有数据,在ExpressJS中处理数据
我收到一个req.body
,其中包含一个更新字段的JSON列表。其中一些字段在Postgres中存储为JSONB。如果传入字段是JSONB,则发出请求的表单(外部代码)已经运行了jsonpatch.compare()
,以生成修补程序列表,传入的是这些修补程序,而不是完整的值。对于任何非JSONB值,传入值只需要传递到UPDATE
查询
我有一个工作版本,如下所示,它假装表中现有的JSONB值为NULL。显然,这不是我们所需要的。我需要从数据库中提取值。当前值版本和最小路由器的非查询,如下所示:
const express=require('express'))
const bodyParser=require('body-parser')
常量SQL=require('SQL-template-strings')
const{Client}=require('pg')
const dbConfig=require(“../db”)
const jsonpatch=require('fast-json-patch')
const FormRouter=express.Router()
我有一些更新代码:
````javascript
常量patchFormsRoute=(请求、恢复)=>{
const client=新客户端(dbConfig)
const{id}=req.body
常量部分=[]
常量参数=[id]
//“表单”表的JSONB字段列表
const jsonFields=[
"部分",,
"编辑",,
“说明”,
]
//所有字段的列表,包括“表单”表中的JSONB字段
常量可能字段=[
"地位",,
“版本”,
"细节",,
"材料",,
…Jsonields,
]
//这是一个伪记录,而不是client.query的结果
让currentRecord={'sections':[],'editors':[],'descriptions':[]
可能字段forEach(myProp=>{
如果(请求正文[myProp]!=未定义){
parts.push(`${myProp}=$${params.length+1}`)
if(jsonFields.indexOf(myProp)>-1){
val=currentRecord[myProp]
jsonpatch.applyPatch(val,请求主体[myProp])
params.push(JSON.stringify(val))
}否则{
参数推送(请求主体[myProp])
}
}
})
const updateQuery='updateforms SET'+parts.join(',')+'WHERE id=$1'
client.connect()
返回客户端
.query(updateQuery,参数)
.then(result=>res.status(200.json)(result.rowCount))
.catch(err=>res.status(400).json(err.severity))
.然后(()=>client.end())
}
FormRouter.route(“/”)
.patch(bodyParser.json({limit:'50mb'}),patchFormsRoute)
exports.FormRouter=FormRouter
我保证,这是有效的代码,它几乎满足了我的需要。但是,我想用表中已经存在的数据替换虚拟记录,这些数据是同时获取的。我的问题是,因为多个客户机可能同时更新一行(但查看JSONB值的正交元素),我需要将fetch、calc和update作为单个事务进行。我的计划是:
id
req.body
或修补行,具体取决于字段是否为JSONB)我试着实现@midrizi的答案;也许只有我一个人,但是等待和简单的res测试的结合让服务器进入了超空间。。。以超时结束。如果有人仍然醒着,这里有一个有效的解决方案 TLDR;RTFM:减去池(目前)
为什么捕获后会出现
然后?以确保无论发生什么情况,客户端都已关闭
const patchFormsRoute = (req, res) => {
const { id } = req.body
// list of JSONB fields for the 'forms' table
const jsonFields = [
'sections',
'editors',
'descriptions',
]
// list of all fields, including JSONB fields in the 'forms' table
const possibleFields = [
'status',
'version',
'detail',
'materials',
...jsonFields,
]
const parts = []
const params = [id]
;(async () => {
const client = await new Client(dbConfig)
await client.connect()
try {
// begin a transaction
await client.query('BEGIN')
// get the current form data from DB
const fetchResult = await client.query(
SQL`SELECT * FROM forms WHERE id = ${id}`,
)
if (fetchResult.rowCount === 0) {
res.status(400).json(0)
await client.query('ROLLBACK')
} else {
const currentRecord = fetchResult.rows[0]
// patch JSONB values or update non-JSONB values
let val = []
possibleFields.forEach(myProp => {
if (req.body[myProp] != undefined) {
parts.push(`${myProp} = $${params.length + 1}`)
if (jsonFields.indexOf(myProp) > -1) {
val = currentRecord[myProp]
jsonpatch.applyPatch(val, req.body[myProp])
params.push(JSON.stringify(val))
} else {
params.push(req.body[myProp])
}
}
})
const updateQuery =
'UPDATE forms SET ' + parts.join(', ') + ' WHERE id = $1'
// update record in DB
const result = await client.query(updateQuery, params)
// commit transaction
await client.query('COMMIT')
res.status(200).json(result.rowCount)
}
} catch (err) {
await client.query('ROLLBACK')
res.status(400).json(err.severity)
throw err
} finally {
client.end()
}
})().catch(err => console.error(err.stack))
}