PostgreSQL jsonb_array_elements包含Hash元素数组

时间:2016-04-20 02:30:52

标签: postgresql postgresql-9.4 jsonb

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

| 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 Dark的弱点的生物(包含任何一个),但也查询类型为Fire Dark的弱点的生物(必须包含两者)。

我找到了一个适用于Fire 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')

1 个答案:

答案 0 :(得分:1)

此处的问题是您必须“查看”数组中的jsonb值,以便您无法使用?&运算符。相反,使用?运算符找到相应的键,并仅选择具有两个匹配的行:

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文档来删除重复项。