具有哈希元素数组的 PostgreSQL jsonb_array_elements

PostgreSQL jsonb_array_elements with array of Hash elements

我有一个 PostgreSQL table(生物),如下所示:

| id <integer> | json <jsonb> |
-------------------------------
|      1       | {"name": "Grooper", "weaknesses":[{"type":"Fire", "value":2},{"type":"Dark", "value":2}]} |
|      2       | {"name": "Zik", "weaknesses":[{"type":"Fire", "value":2}]} |

我正在尝试创建一个过滤弱点类型的查询,这样我就可以过滤所有弱点类型为 Fire [=15= 的生物](包含任何一个),但也查询具有 Fire Dark 类型弱点的生物(必须包含两者)。

我找到了一个适用于 Fire or Dark:

的查询
select 
  distinct c.* 
from 
  creatures c, 
  jsonb_array_elements(json->'weaknesses') as weakness 
where weakness->'type' ?| array['Fire','Dark']

我怎样才能让这个查询过滤 Fire Dark 类型的生物?

更新:

我有一个查询似乎可以完成我想要的,但它看起来并不漂亮。有什么建议吗?

SELECT * FROM creatures
WHERE 'Fire' in (SELECT jsonb_array_elements(json->'weaknesses')->>'type') 
AND 'Dark' in (SELECT jsonb_array_elements(json->'weaknesses')->>'type')

这里的问题是您必须 "look into" 数组中的 jsonb 值,因此您不能使用 ?& 运算符。相反,使用 ? 运算符和 select 仅找到具有两次命中的那些行:

SELECT DISTINCT id, json
FROM creatures
JOIN LATERAL jsonb_array_elements(json->'weaknesses') ON value ? 'Dark' OR value ? 'Fire'
GROUP BY 1, 2
HAVING count(id) = 2;

顺便说一句,如果 id 是唯一的(也许是主键?),那么 SELECT DISTINCT ON (id) id, json ... 会快得多,因为不必检查 jsonb 文档来删除重复项。