关于PostgreSQL JSONB的匹配和交集问题

 更新时间:2021年09月13日 15:46:37   作者:ccat  
这篇文章主要介绍了PostgreSQL JSONB的匹配和交集问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

PostgreSQL 自从支持 JSONB 到现在,已经有十余年,这十多年来,社区为 JSONB 提供了很多强大的功能。就我个人而言,其实最常用的还是匹配操作 @> 。

把JSON数据看作一个抽象语法树(AST)的话,这个操作符判断右参数是不是左参数的子图。

这里本来应该有个图示, 但是周末的时候临时有个数据集在处理,所以没有时间去找合适的工具了。简单举几个例子,下面这个例子得到true,这应该很好理解:

select '{"a": 1, "b": 2, "c": 3}'::jsonb @> '{"b":2}' ;
--------------
t

而它也可以匹配更复杂的情况,下面这个例子也是 true:

select '{"a": 1, "b": 2, "c": {"value": 3}}'::jsonb @> '{"c":{"value": 3}}';
 ?column?
----------
 t
(1 row)

下面这个例子可能新用户会有点儿迷惑,但是其实也很好的契合了这个规则:

select '{"a": 1, "b": 2, "c": {"value": 3}}'::jsonb @> '{"c":{}}';
 ?column?
----------
 t
(1 row)

但是应该注意的是,下面这个例子结果是 false:

select '{"a": 1, "b": 2, "c": {"value": 3}}'::jsonb @> '{"c":[]}';
 ?column?
----------
 f
(1 row)

这也不难理解,{} 和 [] 不相等。

下面这个例子比较有意思:

select '{"a": 1, "b": 2, "c": {"value": [1, 2, 3]}}'::jsonb @> '{"c":{"value": [2]}}';
 ?column?
----------
 t
(1 row)

这里要注意的是,比较一个 JSON 数组是否匹配另一个时,它并不要求两个数组的顺序相等,只要右边是左边的真子集就可以:

select '{"a": 1, "b": 2, "c": {"value": [1, 2, 3]}}'::jsonb @> '{"c":{"value": [2]}}';
 ?column?
----------
 t
(1 row)
 
select '{"a": 1, "b": 2, "c": {"value": [1, 2, 3]}}'::jsonb @> '{"c":{"value": [5, 2]}}';
 ?column?
----------
 f
(1 row)
 
select '{"a": 1, "b": 2, "c": {"value": [1, 2, 3]}}'::jsonb @> '{"c":{"value": [3, 2]}}';
 ?column?
----------
 t
(1 row)

这个规则契合了PostgreSQL的倒排索引,PostgreSQL的gin索引,JSONB 字段类型和匹配操作 @> 成为了一个非常有力的组合。在过去几年里,我习惯为一些重要的业务表加上一个类型为 JSONB 的meta 字段,并对其建立 gin 索引

create index idx_xxx_meta on xxx using(gin);

需要注意的是指定索引类型时的 create index 语法。

这样的设计可以解决很多传统上难以解决的问题,例如我可以给每个条目打上一个 tag 列表,取带有某几个 tag 的条目就是一个简单的匹配查询:

select xxx from data_table where meta @> '{"tags": ["tag1", "tagx", "tagy"]}'

因为有gin索引的帮助,这个搜索的性能足够常规的互联网应用所需。

甚至我的在 CSDN NLP 组的同事还挖掘出了新的用法。我们在一个存储树节点的表里,保存了一个 meta 字段,其中有一个 path 列表,存储当前字段在树中的路径,它的每一项都是 {"id": node_id, "title": something}这样的结构,而我们搜索某一个节点下面的所有子节点,包括其隔代的子节点时,仅需要执行这样一个查询:

select xxx from tree_node where meta @> '{"path": [{"id": node_id}]}'

当然这个匹配操作也有它的限制,它在右边是左边的真子图的情况下才会匹配成功。例如我希望查找 tags 列表中包含我搜索项中的任何一个(即两者存在非空交集)的情况,用这种方法就不行了。此时我们需要另一个运算符 ?|

select '["tag1", "tag2", "tag3"]'::jsonb ?| '{tag2, tag3}';
 ?column?
----------
 t
(1 row)
 
select '["tag1", "tag2", "tag3"]'::jsonb ?| '{tag2, tag3, tag5}';
 ?column?
----------
 t
(1 row)
 
select '["tag1", "tag2", "tag3"]'::jsonb ?| '{tag5}';
 ?column?
----------
 f
(1 row)

注意这几个例子,首先右边的运算符不再是jsonb,而必须是 text[],其次它其实是检查 key 值——也就是可以通过 gin 索引存储的值:

select '{"tag1":1, "tag2":2, "tag3":3}'::jsonb ?| '{tag5}';
 ?column?
----------
 f
(1 row)
 
select '{"tag1":1, "tag2":2, "tag3":3}'::jsonb ?| '{tag3}';
 ?column?
----------
 t
(1 row)
 
select '{"tag1":1, "tag2":2, "tag3":3}'::jsonb ?| '{tag3, tag1}';
 ?column?
----------
 t
(1 row)

PostgreSQL 支持 JSON 和 JSONB 已经有十余年,每一个版本都在积极的增强其 JSON 数据处理能力,即使我近十年来的积极探索和学习,也没有全面的了解。这个交集运算也是近期在 NLP 组的工作过程中才注意到的。

到此这篇关于PostgreSQL JSONB的匹配和交集的文章就介绍到这了,更多相关PostgreSQL JSONB内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 解决postgresql 序列跳值的问题

    解决postgresql 序列跳值的问题

    这篇文章主要介绍了解决postgresql 序列跳值的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • PostgreSQL教程(十七):客户端命令(1)

    PostgreSQL教程(十七):客户端命令(1)

    这篇文章主要介绍了PostgreSQL教程(十七):客户端命令(1),本文讲解了createdb、dropdb、reindexdb、vacuumdb、createuser、dropuser等命令,需要的朋友可以参考下
    2015-05-05
  • 基于PostgreSQL 权限解读

    基于PostgreSQL 权限解读

    这篇文章主要介绍了基于PostgreSQL 权限解读,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • PostgreSql 重建索引的操作

    PostgreSql 重建索引的操作

    这篇文章主要介绍了PostgreSql 重建索引的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • pgsql 如何删除仍有活动链接的数据库

    pgsql 如何删除仍有活动链接的数据库

    这篇文章主要介绍了pgsql 删除仍有活动链接的数据库操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • 使用postgresql 模拟批量数据插入的案例

    使用postgresql 模拟批量数据插入的案例

    这篇文章主要介绍了使用postgresql 模拟批量数据插入的案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • 将PostgreSQL的数据实时同步到Doris的技巧分享

    将PostgreSQL的数据实时同步到Doris的技巧分享

    众所周知,在两个毫不相干的数据管理系统之间进行数据同步,特别是实时同步,其复杂程度足以让高级DBA脑瓜疼,本文给大家介绍了将PostgreSQL的数据实时同步到Doris的技巧分享,需要的朋友可以参考下
    2024-03-03
  • PostgreSQL报错 解决操作符不存在的问题

    PostgreSQL报错 解决操作符不存在的问题

    这篇文章主要介绍了PostgreSQL报错 解决操作符不存在的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • postgresql安装及配置超详细教程

    postgresql安装及配置超详细教程

    这篇文章主要介绍了postgresql安装及配置超详细教程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • PostgreSQL怎么创建分区表详解

    PostgreSQL怎么创建分区表详解

    数据库表分区把一个大的物理表分成若干个小的物理表,并使得这些小物理表在逻辑上可以被当成一张表来使用,下面这篇文章主要给大家介绍了关于PostgreSQL怎么创建分区表的相关资料,需要的朋友可以参考下
    2022-06-06

最新评论