Postgres搜索包含特定值

时间:2017-10-30 20:20:12

标签: arrays json postgresql jsonb

我的users表中有一个名为“global_settings”的jsonb列。在这里,用户可以配置一个名为“别名”的键,其中包含以下形式的对象数组:

[{"email":"test1@test1.com","active":true},{"email":"test2@test2.com","active":true}]

我想要做的是搜索所有用户,看看是否有特定电子邮件的别名,例如“test1@test1.com”。我的一个用户在他的别名数组中有这个,如上所述,所以我可以测试搜索。

我尝试了这些查询,但它们没有返回任何结果:

select * from users where team_id = 1 and (global_settings->'aliases')::jsonb @> '"test1@test1.com"'

select * from users where team_id = 1 and (global_settings->'aliases')::jsonb ? '"test1@test1.com"'

select * from users where team_id = 1 and (global_settings->'aliases')::jsonb ? 'test1@test1.com'

然而,这确实会返回团队1中配置了“别名”的所有用户,但当然不允许我查找特定的电子邮件:

select * from users where team_id = 1 and (global_settings->'aliases')::jsonb is not null

我是如何搜索具有特定电子邮件别名的用户的?

编辑:

从以下Vao的回答中获得灵感(谢谢!),我想出了这个以获得包含特定电子邮件的完整用户行:

select * from users as u 
inner join (select id,jsonb_array_elements(
(global_settings->'aliases')::jsonb)->>'email' = 'test1@test1.com' 
as alias from users 
where team_id = 1) as u2 
on u2.alias = true and u.id = u2.id

1 个答案:

答案 0 :(得分:1)

with users(team_id,global_settings) as (values(1,'{"aliases":[{"email":"test1@test1.com","active":true},{"email":"test2@test2.com","active":true}]}'::jsonb)
)
, e as (select *,(jsonb_array_elements(global_settings->'aliases')->>'email' = 'test1@test1.com')::int from users where team_id = 1)
select *, bit_or(int4) from e group by team_id,global_settings,int4 having bit_or(int4)::boolean;
 team_id |                                              global_settings                                              | int4 | bit_or
---------+-----------------------------------------------------------------------------------------------------------+------+--------
       1 | {"aliases": [{"email": "test1@test1.com", "active": true}, {"email": "test2@test2.com", "active": true}]} |    1 |      1
(1 row)

这里我使用jsonb_array_elements来取消数组和bit_or(如果组中至少有一个为真,则返回true)来检查这样的值是否存在