如何在 JSON Postgres 数据类型列中搜索特定字符串?

Posted

技术标签:

【中文标题】如何在 JSON Postgres 数据类型列中搜索特定字符串?【英文标题】:How do I search for a specific string in a JSON Postgres data type column? 【发布时间】:2018-02-01 14:53:47 【问题描述】:

我在名为 reports 的表中有一个名为 params 的列,其中包含 JSON。

我需要在 JSON 数组的任意位置找到包含文本“authVar”的行。我不知道文本可能出现的路径或级别。

我只想使用标准的类似运算符搜索 JSON。

类似:

SELECT * FROM reports
WHERE params LIKE '%authVar%'

我已经搜索和谷歌搜索并阅读了 Postgres 文档。我不太了解 JSON 数据类型,并且认为我遗漏了一些简单的东西。

JSON 看起来像这样。

[  
     
      "tileId":18811,
      "Params":  
         "data":[  
              
               "name":"Week Ending",
               "color":"#27B5E1",
               "report":"report1",
               "locations":  
                  "c1":0,
                  "c2":0,
                  "r1":"authVar",
                  "r2":66
               
            
         ]
      
   
]

【问题讨论】:

【参考方案1】:

Postgres 11 或更早的版本中,可以递归遍历未知的 json 结构,但这会相当复杂且成本高昂。我会提出 brute force 应该很好用的方法:

select *
from reports
where params::text like '%authVar%';
-- or 
-- where params::text like '%"authVar"%';
-- if you are looking for the exact value

查询速度非常快,但如果搜索的字符串是其中一个键的一部分,则可能会返回意外的额外行。

Postgres 12+ 中,JSONB 中的递归搜索非常适合 jsonpath 的新功能。

查找包含authVar的字符串值:

select *
from reports
where jsonb_path_exists(params, '$.** ? (@.type() == "string" && @ like_regex "authVar")')

json 路径:

$.**                     find any value at any level (recursive processing)
?                        where
@.type() == "string"     value is string
&&                       and
@ like_regex "authVar"   value contains 'authVar'

或者找到确切的值:

select *
from reports
where jsonb_path_exists(params, '$.** ? (@ == "authVar")')

阅读文档:

The SQL/JSON Path Language jsonpath Type

【讨论】:

递归遍历有什么好处? 本教程详细讲解“params::text”:postgresqltutorial.com/postgresql-cast @CaleSweeney - 当我们搜索与某个键相同的属性时,这个简单的解决方案将失败。 有没有办法使用带有多个参数且不区分大小写的“jsonb_path_exists”? @ersu - 是的,请阅读文档中的9.15.2.2. Regular Expressions。

以上是关于如何在 JSON Postgres 数据类型列中搜索特定字符串?的主要内容,如果未能解决你的问题,请参考以下文章

在 slick、scala 中处理 Postgres json 数据类型

Json 类型列元素更新 - Postgres

使用 Spring / JPA 写入 Postgres 数据库的 JSON 列

在Rails中为Postgres JSON列设置默认值< 4

在 postgres spring-boot + eclipselink 中保存为 JSON 数据类型的替代解决方案

如何在 Postgres 9.4 中对 JSONB 类型的列执行更新操作