我的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
答案 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)来检查这样的值是否存在