【问题标题】:Postgres : can't make JSONB_PATH_EXISTS work correctlyPostgres:无法使 JSONB_PATH_EXISTS 正常工作
【发布时间】:2021-12-03 19:58:55
【问题描述】:

我正在努力使用JSONB_PATH_EXISTS Postgres 函数

我正在使用 PG 12 并遵循此文档:https://www.postgresql.org/docs/12/functions-json.html

使用以下请求(在 DBFiddle 上测试它:https://dbfiddle.uk/?rdbms=postgres_12&fiddle=d5aa984182852438c6f71cf5fa70324e):

select 
    json
from (
    select '{
        "fields": {
            "foo": true,
            "number": 3,
            "listnb": [3, 4],
            "listenb2": ["3", "4"],
            "txt": "hello how are you",
            "listtxt": ["hello","how","are", "you", "3"],
            "nullval": null
        }

    }'::jsonb as json
) t
where 1=1
-- Works with 'strict'
AND JSONB_PATH_EXISTS(json -> 'fields' -> 'listtxt',  'strict $ ? (@.type() == "array")')

-- Doesn't work without 'strict'. Why ?
--AND JSONB_PATH_EXISTS(json -> 'fields' -> 'listtxt',  '$ ? (@.type() == "array")')

-- Can't add a nested condition on an array element value (syntax error)
--AND JSONB_PATH_EXISTS(json -> 'fields' -> 'listtxt',  'strict $ ? (@.type() == "array" && @[*] ? (@ == "how"))')
;

#1 - 如果没有strict 模式,我无法让 type() 函数工作

这可能与松散模式自动展开数组有关,但文档明确指出调用type() 函数时并未完成:

如果 JSON 数据不符合预期的模式,松散模式有助于匹配 JSON 文档结构和路径表达式。 [...] 仅在以下情况下不执行自动展开:

  • 路径表达式包含 type() 或 size() 方法,它们分别返回数组中元素的类型和数量。
  • [...]

所以我不明白为什么我们的结果会有所不同

#2 我无法让嵌套条件工作(示例请求中的第三个AND

根据文档中的示例,语法看起来不错,但我有一个我不理解的语法错误。

感谢您的帮助

【问题讨论】:

  • 您到底想达到什么目的?查找listtxt 为数组的所有行?
  • 在学期,如果字段是数组或字段是“普通”值,我想应用不同的过滤器。所以目前我正在使用不同的 PG 函数来看看我如何区分类型(看起来 type() 函数正在做这项工作),但我不明白为什么我不能在之后添加嵌套条件>

标签: json postgresql postgresql-12


【解决方案1】:

如果您将完整的 JSON 值传递给函数,则以下工作:

where jsonb_path_exists(json, '$ ? (@.fields.listtxt.type() == "array")')

但是我可能会简单地使用 jsonb_typeof() 而不使用路径查询

where jsonb_typeof(json -> 'fields' -> 'listtxt') = 'array'

【讨论】:

  • 谢谢你的提示,它确实有效,但它背后的逻辑是什么?不起作用:JSONB_PATH_EXISTS(json -> 'fields' -> 'listtxt', '$ ? (@.type() == "array")') 不起作用:JSONB_PATH_EXISTS(json, '$.fields.listtxt ? (@.type() == "array")') 起作用:JSONB_PATH_EXISTS(json, '$ ? (@.fields.listtxt.type() == "array")')。这真的是一种奇怪的行为,不是吗?
  • 我认为如果@ 引用数组,它会自动扩展它的元素,所以@ 不直接引用数组的任何表达式都可以工作,例如`'$.fields ? (@.listtxt.type() == "array")' 也可以
猜你喜欢
  • 1970-01-01
  • 2016-12-01
  • 2018-06-01
  • 1970-01-01
  • 2015-05-04
  • 1970-01-01
  • 2016-12-30
  • 2015-06-08
相关资源
最近更新 更多