对平面 jsonb 数组的元素进行 LIKE 查询

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

我有一个 Postgres 表

posts
,其中有一列类型为
jsonb
,它基本上是一个平面标签数组。

我需要做的是以某种方式对该

tags
列元素运行 LIKE 查询,以便我可以找到具有以某些部分字符串开头的标签的帖子。

在 Postgres 中这样的事情可能吗?我不断地发现超级复杂的例子,但没有人描述过如此基本和简单的场景。

我当前的代码可以很好地检查是否有具有特定标签的帖子:

select * from posts where tags @> '"TAG"'

我正在寻找一种在

的行中运行某些东西的方法
select * from posts where tags @> '"%TAG%"'
arrays postgresql pattern-matching jsonb postgresql-9.6
1个回答
7
投票
SELECT *
FROM   posts p
WHERE  EXISTS (
   SELECT FROM jsonb_array_elements_text(p.tags) tag
   WHERE  tag LIKE '%TAG%'
   );

相关,并附说明:

或者使用

@?
运算符更简单,因为 Postgres 12 实现了 SQL/JSON:

SELECT *
--     optional to show the matching item:
--   , jsonb_path_query_first(tags, '$[*] ? (@ like_regex "^ tag" flag "i")')
FROM   posts
WHERE  tags @? '$[*] ? (@ like_regex "TAG")';

运算符

@?
只是函数
jsonb_path_exists()
的包装。所以这是等价的:

...
WHERE  jsonb_path_exists(tags, '$[*] ? (@ like_regex "TAG")');

都没有指数支持。 (稍后可能会添加

@?
运算符,但尚未在第 13 页中添加)。所以对于大表来说这些查询很慢。标准化设计,就像劳伦兹已经建议的那样会更好 - 带有三元组索引:

对于前缀匹配

LIKE 'TAG%'
,无前导通配符),您可以使其与全文索引一起使用:

CREATE INDEX posts_tags_fts_gin_idx ON posts USING GIN (to_tsvector('simple', tags));

以及匹配的查询:

SELECT *
FROM   posts p
WHERE  to_tsvector('simple', tags)  @@ 'TAG:*'::tsquery

或者如果您想要自然英语语言的词干,请使用

english
字典而不是
simple
(或任何适合您情况的内容)。

to_tsvector(json(b))
需要 Postgres 10 或更高版本。

相关:

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