如何更新Postgresql的Jsonb数组

假设你决定将数据以json或者jsonb的形式存储在数据库中,然后发现你刚刚给自己制造了新的问题,而这些问题是以前没有的。

jsonb是一个强大的工具,但它也有一定的代价,因为你需要调整查询和处理数据的方式。

而且将整个jsonb对象加载到内存中,用你喜欢的编程语言进行转换,然后将其保存回数据库,这并不罕见。但是,你刚刚创造了另一个问题:性能瓶颈和资源浪费。

在这篇文章中,我们来看看如何通过一次查询来更新数组内对象的特定值。

假设你正在实现一个为每个客户存储动态联系人功能,那么你就会想到将联系人存储为jsonb列,因为他们是动态的,因此使用非关系型数据结构是有意义的。

然后创建一个带有jsonb列联系人,并在其中插入一些数据。

create table customers (name varchar(256), contacts jsonb);insert into customers (name, contacts) values ('Jimi','[{"type": "phone", "value": "+1-202-555-0105"},{"type": "email", "value": "jimi@gmail.com"}]'
);insert into customers (name, contacts) values ('Janis','[{"type": "email", "value": "janis@gmail.com"}]'
);

看起来很简单,但是如何更新特定的联系人信息?如何更改jimi的电子邮件或者janis的电话?

幸运的是,PostgreSQL提供了json_set函数。函数原型:

jsonb_set(target jsonb, path text[], new_value jsonb[, create_missing boolean])

给定一个jsonb列,可以在指定的路径上设置一个新值。

select jsonb_set('[{"type": "phone", "value": "+1-202-555-0105"},{"type": "email", "value": "jimi@gmail.com"}]','{1,value}','"jimi.hendrix@gmail.com"',false
);select jsonb_set('[{"type": "email", "value": "janis@gmail.com"}]','{0,value}','"janis.joplin@gmail.com"',false
);

jsonb_set函数的第一个参数为jsonb数据对象,第二个参数路径,在上面的例子中,{1,value}为数组中索引为1的元素,并且属性是value字段的,最后一个参数是对路径中选择的字段进行赋值。

根据这样的规则,那么第一个sql语句就是修改jimi的邮箱,而第二个sql语句就是修改janis的电子邮箱。

上面返回的结果是:

[{"type":"phone","value":"+1-202-555-0105"},{"type":"email","value":"jimi.hendrix@gmail.com"}]
[{"type":"email","value":"janis.joplin@gmail.com"}]

如果现在你认为这样就完事了,那就是你太Too young! Too simple!

非关系型数据库的问题在于它们是动态的,这也是使用jsonb的原因之一,但是这就带来了一个问题,例如上面的案例,jimi的邮箱对象在数组中的索引是1,janis的邮箱对象在数组中索引是0,而另外的一条数据很可能是不同的数组,其索引也不一样,那么如何确定每个联系人的邮箱所在数组的索引?

答案 是对数组中的元素进行排序,并获得索引。

select index-1 as indexfrom customers,jsonb_array_elements(contacts) with ordinality arr(contact, index)where contact->>'type' = 'email'and name = 'Jimi';

该查询会返回1,这是jimi联系人的电子邮件对象索引。

现在万事俱备,只欠东风!我们把查询和更改步骤合并。

with contact_email as (select ('{'||index-1||',value}')::text[] as pathfrom customers,jsonb_array_elements(contacts) with ordinality arr(contact, index)where contact->>'type' = 'email'and name = 'Jimi'
)
update customersset contacts = jsonb_set(contacts, contact_email.path, '"jimi.hendrix@gmail.com"', false)from contact_emailwhere name = 'Jimi';

这个sql中最重要的部分就是with,这是一个强大的命令,但对于这个例子来说,你可以把它看成是“储存变量”功能,with最后的结果都储存在contact_email变量内,其中就包含需要更新的路径,也就是jimi的邮箱路径。

下面再稍微详细介绍一下:

(‘{‘||index-1||’,value}’)::text[] as path

这一段是在建立路径{1, value},但是要转换成text[]类型,因为jsonb_set函数需要这个类型。

如何更新Postgresql的Jsonb数组相关推荐

  1. Mybatis调用PostgreSQL存储过程实现数组入参传递

    前言 项目中用到了Mybatis调用PostgreSQL存储过程(自定义函数)相关操作,由于PostgreSQL自带数组类型,所以有一个自定义函数的入参就是一个int数组,形如: CREATE OR ...

  2. PostgreSQL 多重含义数组检索与条件过滤 (标签1:属性, 标签n:属性) - 包括UPSERT操作如何修改数组、追加数组元素

    摘要: 标签 PostgreSQL , 多重函数数组 , UDF索引 , 过滤 , 文本处理 背景 PG的数组类型,被广泛应用于 画像系统 , 标签系统. 在一些业务重建中,对数组内容的定义往往包含了 ...

  3. golang操作postgresql数据库jsonb类型

    golang操作postgresql数据库jsonb类型 本文以案例为主,少言,自悟. 推荐一个测试sql的网站 SQL操作 // 创建一个带有jsonb列的表 CREATE TABLE items ...

  4. PostgreSQL jsonb 数组的增删改查

    有时候我们需要使用PostgreSQL这种结构化数据库来存储一些非结构化数据,PostgreSQL恰好又提供了json这种数据类型,这里我们来简单介绍使用jsonb的一些常见操作. PostgreSQ ...

  5. mongo更新数组字段_更新mongodb中嵌套数组中的几个字段(使用pymongo)

    我正在尝试更新数组内数组中的一些字段 示例文档如下:{ id: 987654321 tweets: [ { text: "RT @947FreshFM: A vigil will be he ...

  6. PostgreSQL处理jsonb中的arrays of array 类型

    一.提出问题 在postgre数据库,遇到了数组内嵌套数组的jsonb存储格式,如下: SELECT * FROM public.keyword_trend 查询结果: 其中,history一栏[[& ...

  7. PostgreSQL中JSONB的索引

    JSONB类型的列上可以直接建索引,支持BTree索引和GIN索引.其中,GIN索引可以高效的从JSONB内部的key/value对中搜索数据,因此JSONB类型上常用GIN索引. JSONB上创建G ...

  8. jsonb 查询_如何使用IN运算符查询jsonb数组

    小编典典 简短答案 您可以jsonb_array_elements()在横向联接中使用该函数,并value在WHERE子句中的复杂表达式中使用其结果: SELECT t.* FROM test t C ...

  9. postgresql 遍历字符串数组_每日一道编程题(348):1005.K次取反后最大化的数组和...

    1005.K次取反后最大化的数组和 每日编程中遇到任何疑问.意见.建议请公众号留言或直接撩Q474356284(备注每日编程) 给定一个整数数组 A,我们只能用以下方法修改该数组:我们选择某个个索引  ...

最新文章

  1. linux下压缩工具总结与使用(参考私房菜)
  2. 解决远程连接超过最大连接数问题
  3. matlab crf 工具包,python调用CRF++工具包
  4. 如何实现手游app瘦身?
  5. [转]c#调用API截图
  6. 雷达的工作原理示意图_电磁阀的构成和工作原理示意图
  7. 07.30《jQuery》——1.1DOM对和jQuery对象的转化
  8. 工作总结 EntityFramework中出现DateTime2异常的完美解决办法
  9. django-添加学生的制作-模块的封装
  10. android http 416,HTTP 416 错误 – 所请求的范围无法满足 (Requested Range not satisfiable)...
  11. inquirer:命令行中与用户进行交互的js库
  12. 企业微信代开发获取应用Secret
  13. apng java,免费的APNG、WebP格式转换工具-iSparta
  14. 2019“智汇科学城”光明区创新企业投融资路演在招商局智慧城顺利举办
  15. C++与C#相比,哪个更适合开发大型游戏?
  16. cisco配置主机计算机连接,思科交换机路由器 连接配置步骤
  17. html中repeat的作用,深入探究CSS repeat()函数知识及用法
  18. javaWEB——主页面新闻展示删除查看修改主题绑定
  19. UF2.0、O4、UFT、TA众明星背后的秘密
  20. 无需QQ密保直接修改QQ密码

热门文章

  1. BugkuCTF-WEB题文件包含
  2. c 调用mysql密码为空_C语言连MySQL - osc_srnunz15的个人空间 - OSCHINA - 中文开源技术交流社区...
  3. matlab 计算汉明距_matlab实现滑动平均滤波
  4. mysql查看版本号_十分钟了解MySQL事务机制
  5. [LCP28] 采购方案
  6. centos 使用java_如何在CentOS 8上安装Java
  7. matlab 遗传优化算法_转载 | 遗传算法解决TSP问题的MATLAB实现
  8. gcc编译器java_「gcc编译器下载」gcc编译器下载各版本下载 - seo实验室
  9. 软件设计师c语言算法皇后,软件设计师历年试题-算法.ppt
  10. JAVA的数据类型有哪些?