Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js ES6异步/等待、ExpressJS和Postgres事务 修订问题_Node.js_Postgresql_Async Await_Node Postgres - Fatal编程技术网

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

  • 对于任何JSONB字段,应用补丁在UPDATE语句中为该字段生成正确的值

  • 使用适当的参数值运行UPDATE语句(来自
    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))
    }