首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从React>ExpressJS-> Postgres中修补Postgres JSONB列的最佳方法是什么?

从React>ExpressJS-> Postgres中修补Postgres JSONB列的最佳方法是什么?
EN

Stack Overflow用户
提问于 2020-03-27 18:51:12
回答 1查看 1.3K关注 0票数 0

我有一个大的数据表(使用AG-Grid表示),我希望在Postgres后端中更新它,但是下一部分的最佳方法是让我推诿,在工作量和最佳的操作过程方面。

使用fast-json-patch库,我可以很容易地在客户机中获得一个JSON修补程序列表,然后大致如此:

代码语言:javascript
复制
import * as jsonpatch from 'fast-json-patch'

postData = jsonpatch.compare(originalData, updatedData)

const request = new Request(url, {
    method: 'PATCH',
    body: JSON.stringify(postData),
    headers: new Headers({
      Accept: 'application/json',
      'Content-Type': 'application/json-patch',
      Authorization: 'Bearer ' + user.token,
    }),
  })

然后在ExpressJS‘后端’中迭代一系列jsonb_set查询以更新Postgres。

或者,我可以从Postgres获取要更新的记录,然后使用fast-json-patch在ExpressJS后端中修补JSONB数据,然后一次性更新Postgres记录?

这不是我以前做过的事,但我肯定这是一种很普通的事情。什么是最好的一般方法?

更新

我试图实现第二种方法--我现在的问题是当我有JSONB字段要更新时,锁定/解锁Postgres。我现在的问题是实际实现来自express端的记录锁定和更新,特别是尝试处理使用pg后端的异步特性。

我只是想知道,是否有人能发现(非故意的)错误在这个笨拙的尝试中:

代码语言:javascript
复制
const express = require('express')
const bodyParser = require('body-parser')
const SQL = require('sql-template-strings')
const { Client } = require('pg')
const dbConfig = require('../db')
const client = new Client(dbConfig)
const jsonpatch = require('fast-json-patch')

// excerpt for patch records in 'forms' postgres table

const patchFormsRoute = (req, res) => {
  const { id } = req.body
  const jsonFields = [ 'sections', 'descriptions' ]
  const possibleFields = [ 'name','status',...jsonFields ]
  const parts = []
  const params = [id] // stick id in as first param
  let lockInUse = false

  // find which JSONB fields are being PATCHed.
  // incoming JSONB field values are already JSON 
  // arrays of patches to apply for that particular field

  const patchList = Object.keys(req.body)
    .filter(e => jsonFields.indexOf(e) > -1)

  client.connect()

  if (patchList.length > 0) {
    const patchesToApply = pullProps(req.body, jsonFields)
    lockInUse = getLock('forms',id)
    // return record from pg as object with just JSONB field values
    const oldValues = getCurrentValues(patchList, id)
    // returns record with patches applied
    const patchedValues = patchValues( oldValues , patchesToApply )
  }

  possibleFields.forEach(myProp => {
    if (req.body[myProp] != undefined) {
      parts.push(`${myProp} = $${params.length + 1}`)
      if (jsonFields.indexOf(myProp) > -1) {
        params.push(JSON.stringify(patchedValues[myProp]))
      } else {
        params.push(req.body[myProp])
      }
    }
  })

  result = runUpdate(client, 'forms', parts, params)

  if(lockInUse) {
    releaseLock(client, 'forms', id)
  }

  client.end()

  return result
}

// helper functions to try and cope with async nature of pg

function async getLock(client, tableName, id ) {
  await client.query(SQL`SELECT pg_advisory_lock(${tableName}::regclass::integer, ${id});`)
  return true
}

function async releaseLock(client, tableName, id) {
  await client.query(SQL`SELECT pg_advisory_unlock(${tableName}::regclass::integer, ${id});`)
}

function async getCurrentValues(client, fieldList, id) {
  const fl = fieldList.join(', ')
  const currentValues = await client
    .query(SQL`SELECT ${fl} FROM forms WHERE id = ${id}`)
    .then((result) => {return result.rows[0]})
  return currentValues
}

function pullProps(sourceObject, propList) {
  return propList.reduce((result, propName) => {
    if(sourceObject.hasOwnProperty(propName)) result[propName] = sourceObject[propName]
    return result
  }, {})
}

function patchValues(oldValues, patches) {
  const result = {}
  Object.keys(oldValues).forEach(e => {
    result[e] = jsonpatch.apply( oldValues[e], patches[e] );
  })
  return result
}

function async runUpdate(client, tableName, parts, params) {
  const updateQuery = 'UPDATE ' + tableName + ' SET ' + parts.join(', ') + ' WHERE id = $1'
  const result = await client
    .query(updateQuery, params)
    .then(result => {
      res.json(result.rowCount)
    })
  return result
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-03-28 13:53:28

使用第二种方法。PostgreSQL没有JSONB的就地编辑功能.它总是包括一份完整的副本。您最好在客户机中这样做,因为客户端似乎有更好的工具。

如果修补程序很小,而且JSONB很大,而且您的网络很慢,则可能会有例外。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60892406

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档