You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL中JSONB操作符@?与@@有何差异?为何返回结果不同?

PostgreSQL中@?和@@ JSONB操作符的差异解析

核心本质差异

  • @?:等价于jsonb_path_exists(),作用是检查JSON路径表达式是否能匹配到至少一个节点。只要路径能找到符合条件的非空节点集合,就返回true。
  • @@:等价于jsonb_path_match(),要求路径表达式必须返回单个布尔值,而非节点集合。只有当表达式结果为true时才返回true;若返回节点集合或其他非单个布尔值,操作符会返回false(直接调用jsonb_path_match()不符合要求会报错)。

结合测试案例分析

  1. @?返回t的原因:
    路径$ ?(@.email.main == "hi@example.net")筛选出了符合条件的顶层JSON对象,匹配到了有效节点,因此@?返回t。

    david=# SELECT '{ "email": { "main": "hi@example.net" } }' @? '$ ?(@.email.main == "hi@example.net")';
     ?column? 
    ----------
     t
    
  2. @@直接用相同路径返回f的原因:
    该路径返回的是包含顶层对象的节点集合,不是单个布尔值,不符合@@的约束,因此返回f。直接调用jsonb_path_match()会明确报错ERROR: single boolean result is expected,直观体现了@@的要求。

    david=# SELECT '{ "email": { "main": "hi@example.net" } }' @@ '$ ?(@.email.main == "hi@example.net")';
     ?column? 
    ----------
     f
    
  3. exists()的正确用法:
    你用jsonb_path_match('...', 'exists($ ?(...))')能返回t,是因为exists()将节点集合转换为了单个布尔值。但@@用同样写法返回f,是因为路径里的$多余了——?已经是相对于顶层对象的筛选,正确写法应去掉$:

    david=# SELECT '{ "email": { "main": "hi@example.net" } }' @@ 'exists(?(@.email.main == "hi@example.net"))';
     ?column? 
    ----------
     t
    

    更简洁的写法是直接使用布尔表达式(路径直接返回单个布尔值):

    david=# SELECT '{ "email": { "main": "hi@example.net" } }' @@ '@.email.main == "hi@example.net"';
     ?column? 
    ----------
     t
    

总结

  • 验证是否存在匹配节点时,用@?或jsonb_path_exists();
  • 验证表达式直接返回true时,用@@或jsonb_path_match(),确保路径返回单个布尔值,或用exists()将匹配结果转换为布尔值(注意路径写法)。

内容的提问来源于stack exchange,提问作者theory

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 11:27:11