使用 jsonb_set() 更新特定的 jsonb 数组值

2023-12-19

目前我正在使用 PostgreSQL 9.5 并尝试更新 jsonb 字段数组内的值。但我无法获取所选值的索引

我的桌子看起来像这样:

 CREATE TABLE samples (
    id serial,
    sample jsonb
 );

我的 JSON 看起来像这样:

{"result": [
    {"8410": "ABNDAT", "8411": "Abnahmedatum"},
    {"8410": "ABNZIT", "8411": "Abnahmezeit"},
    {"8410": "FERR_R", "8411": "Ferritin"}
]}

我获取正确值的 SELECT 语句有效:

SELECT 
    id, value 
FROM 
    samples s, jsonb_array_elements(s.sample#>'{result}') r  
WHERE 
    s.id = 26 and r->>'8410' = 'FERR_R';

结果是:

id | value
----------------------------------------------
26 | {"8410": "FERR_R", "8411": "Ferritin"}

好吧,这就是我想要的。现在我想使用以下 UPDATE 语句执行更新以添加新元素“ ratingtext”(如果尚未存在):

UPDATE 
    samples s
SET
    sample = jsonb_set(sample,
              '{result,2,ratingtext}',
              '"Some individual text"'::jsonb,
              true)
WHERE
      s.id = 26;

执行 UPDATE 语句后,我的数据如下所示(也是正确的):

{"result": [
    {"8410": "ABNDAT", "8411": "Abnahmedatum"},
    {"8410": "ABNZIT", "8411": "Abnahmezeit"},
    {"8410": "FERR_R", "8411": "Ferritin", "ratingtext": "Some individual text"}
]}

到目前为止一切顺利,但我manually搜索索引值 2 以获取 JSON 数组中的正确元素。如果顺序改变,这将不起作用。

所以我的问题是:

有没有办法获取所选 JSON 数组元素的索引并将 SELECT 语句和 UPDATE 语句合并为一个?

就像:

UPDATE 
    samples s
SET
    sample = jsonb_set(sample,
              '{result,' || INDEX OF ELEMENT || ',ratingtext}',
              '"Some individual text"'::jsonb,
              true)
WHERE
      s.id = 26;

的价值观样品编号 and "8410"在准备声明之前就已经知道。

或者目前还不可能?


您可以使用以下命令找到搜索元素的索引jsonb_array_elements() with ordinality (note, ordinality从 1 开始,json 数组的第一个索引为 0):

select 
    pos- 1 as elem_index
from 
    samples, 
    jsonb_array_elements(sample->'result') with ordinality arr(elem, pos)
where
    id = 26 and
    elem->>'8410' = 'FERR_R';

 elem_index 
------------
          2
(1 row) 

使用上面的查询根据元素的索引更新元素(请注意,第二个参数jsonb_set()是一个文本数组):

update 
    samples
set
    sample = 
        jsonb_set(
            sample,
            array['result', elem_index::text, 'ratingtext'],
            '"some individual text"'::jsonb,
            true)
from (
    select 
        pos- 1 as elem_index
    from 
        samples, 
        jsonb_array_elements(sample->'result') with ordinality arr(elem, pos)
    where
        id = 26 and
        elem->>'8410' = 'FERR_R'
    ) sub
where
    id = 26;    

Result:

select id, jsonb_pretty(sample)
from samples;

 id |                   jsonb_pretty                   
----+--------------------------------------------------
 26 | {                                               +
    |     "result": [                                 +
    |         {                                       +
    |             "8410": "ABNDAT",                   +
    |             "8411": "Abnahmedatum"              +
    |         },                                      +
    |         {                                       +
    |             "8410": "ABNZIT",                   +
    |             "8411": "Abnahmezeit"               +
    |         },                                      +
    |         {                                       +
    |             "8410": "FERR_R",                   +
    |             "8411": "Ferritin",                 +
    |             "ratingtext": "Some individual text"+
    |         }                                       +
    |     ]                                           +
    | }
(1 row)

最后一个参数在jsonb_set()应该true如果其键尚不存在,则强制添加新值。但是它可能会被跳过,因为它的默认值是true.

尽管并发问题似乎不太可能发生(由于限制性 WHERE 条件和受影响的行数可能很少),但您可能还会感兴趣Postgres 中的原子更新 .. SELECT。 https://stackoverflow.com/questions/11532550/atomic-update-select-in-postgres

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 jsonb_set() 更新特定的 jsonb 数组值 的相关文章

随机推荐

  • 关于createUserWithEmailAndPassword的问题

    我来自中国 当我做作业时 我发现了一些问题 但我无法解决它 这是我的代码 控制台信息 2021 05 28 16 41 32 525 5706 5746 com example chat W System 忽略标头 X Firebase L
  • Android 构建的 ltrace

    伙计们 我正在尝试从这个 repo 构建适用于 Android 的 stracehttps android googlesource com platform external ltrace https android googlesour
  • 更新到 ARC 错误

    我正在尝试将项目更新为 ARC 虽然我看过一些关于更新到 ARC 的帖子 但我见过的帖子都没有处理这个特定问题 我有多个错误 大多数是 ARC Issue Pointer to non const type id with no expli
  • xml 文件未复制到目标 intellij idea

    我在源文件夹中有一些 xml 文件以及 java 文件 Intellij Idea 不会将它们复制到目标文件夹 我希望这些 xml 文件与目标中的类一起出现 Eclipse 做得很好 谁能告诉我如何在 Intellij Idea 中实现这一
  • Java 8 ImageIO 在 Linux 中错误读取 JPEG

    我正在尝试读取用户上传的 JPEG 图像 任意 以在服务器应用程序中创建缩略图 系统在 Windows7 Oracle Java 8u11 中运行良好 但我在服务器上的 CentOS 下遇到颜色模型问题 原始图像是 http studio
  • 如何使用自定义指令作为类在 AngularJS 中使用日期选择器?

    下面是我使用的 HTML 和 Javascript 代码 HTML 代码 div div
  • MySQL 是否有类似 SQL Server TIMESTAMP 列的功能?

    我的初步研究表明 不 我在 SQL Server 中有一个数据库应用程序 它使用 SQL Server 时间戳列来跟踪更改 也就是说 我可以浏览该表并知道 如果我看到时间戳 gt 某个参考时间戳 则该行已被更改添加或更新 我正在寻找 MyS
  • OpenCL 中的障碍

    在 OpenCL 中 我的理解是你可以使用barrier 同步工作组中线程的函数 我 通常 确实了解它们的用途以及何时使用它们 我还知道工作组中的所有线程都必须遇到障碍 否则会出现问题 然而 到目前为止 每次我尝试使用屏障时 似乎都会导致我
  • Highcharts:维恩图如何显示总数和并集数?

    I am using highchart js to generate reports I need to generate venn diagram like the below image 在 的帮助下this post https s
  • 基于 PHP/JavaScript 的安全、可定制、开源聊天引擎,适用于所有流行的浏览器

    请推荐适用于所有流行浏览器的 PHP JavaScript 上的安全 可定制 开源聊天 我自己写的聊天记录
  • 让express.js显示公共文件夹

    我最近使用express js构建了一个快速的单页应用程序 这实际上是我的第一个js框架 实际上 我的第一个js项目 所以我对此非常陌生 我订阅了新的typography com 云字体 但无法找到放置在公共文件夹中的 fonts 文件夹
  • 如何检查Windows文件是否可读/可写?

    首先 我知道这对于实际检查我是否可以写作并不可靠 我正在编写一个文件传输客户端 并且希望 远程 和 本地 文件浏览器窗格之间具有相同的功能 我完全理解 无论如何 我都必须处理执行的任何操作的任何与权限相关的异常 这不是编程检查 只是显示给用
  • 将 TryDequeue 放入 while 循环中安全吗?

    我以前没有使用过并发队列 在 while 循环中使用 TryDequeue 是否可以 难道这事就不能永远陷下去了吗 var cq new ConcurrentQueue
  • 如何在 XML 中创建新行或制表符?

    In my strings xml文件 我有一个很长的文本 我想要格式化 如何在文本的第一句之前添加制表符 另外 新行的代码是什么 Add t对于选项卡和 n对于新线
  • 为什么用函数式语言编写编译器更容易? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我想这个问题很久了 但在 Google 上找不到答案 在 Stackoverflow 上也找不到类似的问题 如果有重复的 我很抱歉 很多人似乎都
  • 使用 vbscript 在命令提示符中执行多个命令

    Set oShell CreateObject WScript Shell oShell Run cmd c c 这条线执行得非常好 现在我需要输入文本 例如 c users gt abcd 我该如何在已经打开的cmd提示符中进行操作 您必
  • 接口类型变量

    我正在学习Java 我看到以下关于界面在一本书中 当变量被声明为接口类型时 它只需 意味着该对象预计已实现该接口 这是什么意思 如果我定义一个界面 public interface Myinterface void method one i
  • 以编程方式查找消息框并生成按钮点击

    我正在尝试自动测试 winform 应用程序 我在与测试代码相同的进程中运行它 因此很容易找到 Net 控件并在它们上模拟用户操作 然而 我遇到了一个消息框 使用标准 MessageBox Show 方法创建 的问题 我怎样才能掌握它并模拟
  • 如何在执行 Environment.Exit() 之前刷新 dotnet 核心应用程序中的所有记录器

    基本上 我遇到了应用程序崩溃并且没有调试日志的老问题 因为应用程序在写入日志之前就终止了 经典的方法是捕获 main 中的所有异常并刷新异常块中的所有日志缓冲区 此外 添加睡眠以降低重新启动速度并允许缓冲区完成刷新 我使用serilog 我
  • 使用 jsonb_set() 更新特定的 jsonb 数组值

    目前我正在使用 PostgreSQL 9 5 并尝试更新 jsonb 字段数组内的值 但我无法获取所选值的索引 我的桌子看起来像这样 CREATE TABLE samples id serial sample jsonb 我的 JSON 看