我一直在尝试理解 PostgreSQL
@?
和 @@
JSONB 运算符 之间的区别。为什么这些返回不同的结果?
david=# SELECT '{ "email": { "main": "[email protected]" } }' @? '$ ?(@.email.main == "[email protected]")';
?column?
----------
t
david=# SELECT '{ "email": { "main": "[email protected]" } }' @@ '$ ?(@.email.main == "[email protected]")';
?column?
----------
f
我想也许它们相当于
jsonb_path_exists()
和 jsonb_path_match()
函数:
david=# SELECT jsonb_path_exists('{ "email": { "main": "[email protected]" } }', '$ ?(@.email.main == "[email protected]")');
jsonb_path_exists
-------------------
t
david=# SELECT jsonb_path_match('{ "email": { "main": "[email protected]" } }', '$ ?(@.email.main == "[email protected]")');
ERROR: single boolean result is expected
这提供了更多信息,
文档中的
jsonb_path_match()
示例显示了exists()
的使用,这似乎确实有效:
david=# SELECT jsonb_path_match('{ "email": { "main": "[email protected]" } }', 'exists($ ?(@.email.main == "[email protected]"))');
jsonb_path_match
------------------
t
但
@@
则不然:
david=# SELECT '{ "email": { "main": "[email protected]" } }' @@ 'exists($ ?(@.email.main == "[email protected]"))';
?column?
----------
f
让我感到困惑。我不明白这里的差异。
归结为
返回指定 JSON 值的 JSON 路径谓词检查的结果。
与您的查询的区别在于 main 有一个元素,但 email 有另一个路径元素而不是值。
SELECT '{ "email": { "main": "[email protected]" } }' @@ '$.email ? (@.main == "[email protected]")';
?栏? |
---|
t |
尝试用这个进行可视化:
SELECT jsonb_path_query('{ "email": { "main": "[email protected]" } }', '$ ?(@.email.main == "[email protected]")');
上面确实返回了一些东西,这为什么是@?是真的。但它返回的不是布尔值“true”,这就是@@为false的原因。并且根本不是布尔值,这就是 jsonb_path_match 给出错误的原因。无论如何,这是我对它的随意解释。
这一切都非常微妙,我发现这些文档很难理解,除非你已经知道他们在说什么。