在JSONB列中查询==

时间:2019-09-21 19:01:10

标签: sql postgresql jsonb

我有一个jsonb列,不幸的是,它非常不可预测,在某些情况下,它的值可能是带有嵌套值的数组:

["UserMailer", "applicant_setup_3", ["5cbffeb7-8d5e-4b52-a475-3cf320b2cee9"]]

有时会是这样的键/值:

[{"reference_id": "5cbffeb7-8d5e-4b52-a475-3cf320b2cee9", "job_dictionary": ["StatusUpdater", "FollowTwitterUsersJob"]}]

有没有一种方法可以像将文本一样对待整个列,并执行like来查询是否可以在大文本块中找到uuid?我想找到所有在jsonb列中存在特定uuid字符串的记录。

查询不需要快速或高效。

3 个答案:

答案 0 :(得分:2)

Postgres使用搜索运算符?来搜索jsonb,但这需要您递归搜索json内容。

尽管不是很有效的方法,一种可能的方法是将对象字符串化并使用LIKE进行搜索:

myjsonb::text LIKE '%"5cbffeb7-8d5e-4b52-a475-3cf320b2cee9"%'
myjsonb::text LIKE '%"' || myuuid || '"%'

Demo on DB Fiddle

答案 1 :(得分:1)

您可以先使用jsonb_array_elements(json)拆分数组元素,然后通过类似运算符

从这些元素中过滤转换的字符串
select q.elm
  from
  (
    select jsonb_array_elements(js) as elm
      from tab
  ) q
 where elm::varchar like '%User%'

elm
----------------------------------------------------------------------------------------------------------------------
"UserMailer"
{"reference_id": "5cbffeb7-8d5e-4b52-a475-3cf320b2cee9", "job_dictionary": ["StatusUpdater", "FollowTwitterUsersJob"]}

Demo

答案 2 :(得分:1)

jsonb operator ?的问题在于它仅考虑顶级 (包括数组元素),而不考虑 值< / em> ,并且没有嵌套对象。

您似乎在寻找任何级别的 数组元素 (不是键)。您可以在jsonb)列的顶部进行全文搜索:

SELECT * FROM tbl
WHERE  to_tsvector('simple', jsonb_column)
    @@ tsquery '5cbffeb7-8d5e-4b52-a475-3cf320b2cee9';

db <>提琴here

to_tsvector()提取所有级别上的数组元素-正是您所需要的。

需要Postgres 10或更高版本。 Postgres 11中的json(b)_to_tsvector()提供了更大的灵活性。

这对于非平凡的表很有吸引力,因为它可以非常有效地支持全文本 index

CREATE INDEX tbl_jsonb_column_fts_gin_idx ON tbl USING GIN (to_tsvector('simple', jsonb_column));

在示例中,我使用'simple'文本搜索配置。您可能需要一种特定于语言的语言,例如'english'。仅查找UUID字符串并不重要,但是针对特定语言的词干可能会使索引变小...

相关:

当您仅查找UUID时,可以使用自定义(IMMUTABLE)函数进行进一步优化,以从JSON文档中提取UUID作为数组(uuid[])并在顶部构建一个功能性GIN索引它的。 (但索引要小得多。)然后:

SELECT * FROM tbl
WHERE  my_uuid_extractor(jsonb_column) @> '{5cbffeb7-8d5e-4b52-a475-3cf320b2cee9}';

这样的函数可能会很昂贵,但对于存储并根据预先计算的值进行操作的函数索引而言,并没有太大关系。