Postgres jsonpath 运算符 like_regex 的变量替换?

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

我想使用正则表达式过滤器查询 JSONB 数组。按照docs,我应该能够做到:

WHERE jsonb_path_exists(
  data,
  '$.value[*] ? (@ like_regex $foo flag "i")',
  jsonb_build_object('foo', 'demo')
)

但我收到错误:

ERROR: syntax error at or near "$foo" of jsonpath input

我认为这是因为

$
是一个有效的正则表达式字符?

这是一些演示数据:

INSERT INTO table_data (fields) VALUES
     ('[{"value": "Sales"}]'),
     ('[{"value": "CEO Staff"}]'),
     ('[{"value": "Procurement"'),
     ('[{"value": "CEO Staff"}]');

我想查询所有包含

'ceo'
的值。

sql postgresql jsonb jsonpath
2个回答
1
投票

我可以重现这个问题。参数替换适用于其他

jsonpath
运算符,例如
==
,但对于
like_regex
则失败。不过手册似乎没有提到这个限制。

我认为这与正则表达式中

$
的特殊含义(用双引号括起来)无关。错误较早出现。看起来那里不支持参数替换。

有一个 解决方法:动态构建

jsonpath
表达式并使用关联的 Postgres 运算符
@?
:

SELECT *
FROM   tbl 
WHERE  data @? format('$[*].value ? (@ like_regex %s flag "i")', '"CEO"')::jsonpath;

小提琴

使用(可选)

format()
方便字符串连接。字符串文字
'"CEO"'
可以用表达式替换 - 我推测的目标用例?
然后投射到
jsonpath

情节转折:无论如何,这都是优越。它可以使用 index - 而不是使用函数

jsonb_path_exists()
! (并且运算符
@?
不允许从一开始就进行参数替换。)
像(除其他外)这样的索引:

CREATE INDEX ON tbl USING gin (data jsonb_path_ops);

密切相关(另请参阅那边附加的小提琴!):

索引的使用在内部绑定到运算符,而不是函数。某些函数可以由查询规划器转换,但在本例中不行。相关:


0
投票

我假设

fields
JSON 数组可能包含多个元素,因此我首先使用横向连接进行展平,然后使用不区分大小写的“regexp-match”运算符进行过滤
~*

select fields, f -- or whatever else you might need
from table_data
cross join lateral jsonb_array_elements(fields) f
where f->>'value' ~* '\yCEO\y';

如果

fields
JSON 数组始终包含一个元素,那么只需

select fields from table_data
where fields->0->>'value' ~* '\yCEO\y';

DB Fiddle 演示

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