在 JSONB 列中查询 =?
Query JSONB column for any value where =?
我有一个 jsonb 列,不幸的是它非常不可预测,在某些情况下它的值可能是一个具有嵌套值的数组:
["UserMailer", "applicant_setup_3", ["5cbffeb7-8d5e-4b52-a475-3cf320b2cee9"]]
有时 key/values 会像这样:
[{"reference_id": "5cbffeb7-8d5e-4b52-a475-3cf320b2cee9", "job_dictionary": ["StatusUpdater", "FollowTwitterUsersJob"]}]
有没有一种方法可以编写一个查询,将整个列视为文本并执行 like
以查看我是否可以在大文本 blob 中找到 uuid?我想找到 jsonb 列中存在特定 uuid 字符串的所有记录。
查询不需要快速或高效。
Postgres 有 jsonb 的搜索运算符 ?
,但这需要您递归搜索 json 内容。
一种可能但不是很有效的方法是将对象字符串化并使用 LIKE
搜索它:
myjsonb::text LIKE '%"5cbffeb7-8d5e-4b52-a475-3cf320b2cee9"%'
myjsonb::text LIKE '%"' || myuuid || '"%'
你可以先用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"]}
jsonb operator ?
的问题是它只考虑顶级keys(包括数组元素),而不是值,没有嵌套对象。
您似乎在寻找值和数组元素 (不是键)在任何级别。您可以在 json
(b
) 列的顶部进行全文搜索:
SELECT * FROM tbl
WHERE to_tsvector('simple', jsonb_column)
@@ tsquery '5cbffeb7-8d5e-4b52-a475-3cf320b2cee9';
db<>fiddle here
to_tsvector()
在 所有级别 上提取 值 和 数组元素 - 只是你需要什么。
需要 Postgres 10 或更高版本。 json(b)_to_tsvector()
在 Postgres 11 中提供了更大的灵活性。
这对于非平凡大小的表格很有吸引力,因为它可以非常有效地支持全文 index:
CREATE INDEX tbl_jsonb_column_fts_gin_idx ON tbl USING GIN (to_tsvector('simple', jsonb_column));
我在示例中使用了 'simple'
文本搜索配置。您可能需要一种特定于语言的语言,例如 'english'
。当您只查找 UUID 字符串时并不重要,但是针对特定语言的词干可能会使索引更小一些...
相关:
- Does the phrase search operator <-> work with JSONB documents or only relational tables?
虽然您只是在寻找 UUID,但您可以使用自定义 (IMMUTABLE
) 函数进一步优化以从 JSON 文档中提取 UUID 作为数组 (uuid[]
) 并构建在其之上的功能性 GIN 索引。 (索引要小得多。)然后:
SELECT * FROM tbl
WHERE my_uuid_extractor(jsonb_column) @> '{5cbffeb7-8d5e-4b52-a475-3cf320b2cee9}';
这样的函数可能很昂贵,但对于存储和操作预计算值的函数索引来说并不重要。
我有一个 jsonb 列,不幸的是它非常不可预测,在某些情况下它的值可能是一个具有嵌套值的数组:
["UserMailer", "applicant_setup_3", ["5cbffeb7-8d5e-4b52-a475-3cf320b2cee9"]]
有时 key/values 会像这样:
[{"reference_id": "5cbffeb7-8d5e-4b52-a475-3cf320b2cee9", "job_dictionary": ["StatusUpdater", "FollowTwitterUsersJob"]}]
有没有一种方法可以编写一个查询,将整个列视为文本并执行 like
以查看我是否可以在大文本 blob 中找到 uuid?我想找到 jsonb 列中存在特定 uuid 字符串的所有记录。
查询不需要快速或高效。
Postgres 有 jsonb 的搜索运算符 ?
,但这需要您递归搜索 json 内容。
一种可能但不是很有效的方法是将对象字符串化并使用 LIKE
搜索它:
myjsonb::text LIKE '%"5cbffeb7-8d5e-4b52-a475-3cf320b2cee9"%'
myjsonb::text LIKE '%"' || myuuid || '"%'
你可以先用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"]}
jsonb operator ?
的问题是它只考虑顶级keys(包括数组元素),而不是值,没有嵌套对象。
您似乎在寻找值和数组元素 (不是键)在任何级别。您可以在 json
(b
) 列的顶部进行全文搜索:
SELECT * FROM tbl
WHERE to_tsvector('simple', jsonb_column)
@@ tsquery '5cbffeb7-8d5e-4b52-a475-3cf320b2cee9';
db<>fiddle here
to_tsvector()
在 所有级别 上提取 值 和 数组元素 - 只是你需要什么。
需要 Postgres 10 或更高版本。 json(b)_to_tsvector()
在 Postgres 11 中提供了更大的灵活性。
这对于非平凡大小的表格很有吸引力,因为它可以非常有效地支持全文 index:
CREATE INDEX tbl_jsonb_column_fts_gin_idx ON tbl USING GIN (to_tsvector('simple', jsonb_column));
我在示例中使用了 'simple'
文本搜索配置。您可能需要一种特定于语言的语言,例如 'english'
。当您只查找 UUID 字符串时并不重要,但是针对特定语言的词干可能会使索引更小一些...
相关:
- Does the phrase search operator <-> work with JSONB documents or only relational tables?
虽然您只是在寻找 UUID,但您可以使用自定义 (IMMUTABLE
) 函数进一步优化以从 JSON 文档中提取 UUID 作为数组 (uuid[]
) 并构建在其之上的功能性 GIN 索引。 (索引要小得多。)然后:
SELECT * FROM tbl
WHERE my_uuid_extractor(jsonb_column) @> '{5cbffeb7-8d5e-4b52-a475-3cf320b2cee9}';
这样的函数可能很昂贵,但对于存储和操作预计算值的函数索引来说并不重要。