我想使用正则表达式筛选器查询JSONBarray.在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'的值.

推荐答案

我可以在当前的postgres 16.0中重现这个问题.参数替换适用于其他jsonpath operators,如==,但不适用于like_regex.然而,手册似乎没有提到这一限制.

我不认为这与regexp表达式中$的特殊含义有关(它会用双引号引起来).错误在更早的时候就开始了.看起来那里就是不支持参数替换.

值得注意的是,手册中提到了value ==101辆,但实际上是string like_regex103辆(突出强调了我的).但这一领先优势持平,因为也有string starts with103的领先优势,变量替代在那里如预期般起作用.

有一个workaround:动态构建jsonpath表达式并使用关联的Postgres operator @?:

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

fiddle

Using (optional) format() for convenient string concatenation. The string literal '"CEO"' can be replaced by an expression - the target use case I presume?
Then cast to jsonpath.

The plot twist: this is superior anyway. It can use an index - as opposed to using the function jsonb_path_exists()! (And the operator @? does not allow for parameter substitution to begin with.)
An index like (among others):

CREATE INDEX ON tbl USING gin (data jsonb_path_ops);

密切相关(也请看那边的小提琴!)

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

Sql相关问答推荐

Postgresql:从jsons数组到单个id索引的json

查询多个表并返回合并在联合列上的所有表中的所有行

出现5次后,将所有正斜杠替换为连字符

为表中每个缺少的引用创建新行

通过之前的连接-这是Oracle的错误吗?

如何在SQL中更新Json字符串

在SQL查询中使用COALESS

如何计算给定日期前三个月的值以及月初数据?

嵌套Json对象的SQL UPDATE WHERE

如何使用Clickhouse的COUNT聚合返回所有列,但GROUP BY是这些列的子集

如何向 mariadb 添加外键?

通过ID和数据找到每个不同的值

将一名成员金额分配给群组内的其他成员

验证某个日期前后的连续代码

如何使用 join 和 where 子句从另一表中仅删除一个表中的值

Oracle PL/SQL长期运行问题

使用 SAVE TRANSACTION 时 BEGIN 和 COMMIT 语句的数量不匹配

PlSql 陷入死循环

使用一组值进行分组和计数

从 JSON 数组中移除对象