查询 JSONB 列中的任意值,其中 =?

问题描述 投票:0回答:3

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

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

有时它会是带有这样的键/值的东西:

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

有没有办法编写一个查询,将整个列视为文本,并执行

like
来查看是否可以在大文本 blob 中找到 uuid?我想找到 jsonb 列中存在特定 uuid 字符串的所有记录。

查询不需要快速或高效。

sql arrays json postgresql jsonb
3个回答
3
投票

Postgres 有用于 jsonb 的搜索运算符

?
,但这需要您递归地搜索 json 内容。

一种可能的方法,虽然不是很有效,但可以将对象字符串化并使用

LIKE
来搜索它:

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

DB Fiddle 上的演示


2
投票

jsonb运算符

?
的问题是它只考虑顶级(包括字符串数组元素),而不是,并且没有嵌套对象。

您似乎正在寻找任何级别的 数组元素(不是键)。您可以通过在

json
(
b
) 列顶部进行全文搜索来获得该信息:

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

db<>小提琴这里

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

需要 Postgres 10 或更高版本。 Postgres 11 中的

json(b)_to_tsvector()
提供了更大的灵活性。

这对于大小不小的表格很有吸引力,因为它可以非常有效地支持全文索引

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}';

这样的函数可能很昂贵,但对于存储和操作预先计算的值的函数索引来说并不重要。


1
投票

您可以首先使用

jsonb_array_elements(json)
拆分数组元素,然后使用 Like 运算符从这些元素中过滤转换后的字符串

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"]}

演示

© www.soinside.com 2019 - 2024. All rights reserved.