假设:
- Postgres 9.4或更高版本 。
“获取所有位于系列5中的用户”的 意思是:
“具有至少一个包含的数组元素{"serie": 5}。可能还有其他。”使用第一个较短的数据格式。没有冗余的“数据”密钥。
简短答案: 使用 jsonb
代替,
json这才有效:
User.where("groups @> ?", '[{"serie": 5}]')请注意方括号,以使右侧操作数成为JSON 数组 。
为什么?
此处的主要误解是:数据类型json
与相同 jsonb
。
您没有声明实际的表定义,但稍后进行了注释
json,问题中有一个提示:
select json_array_elements(groups -> 'data') ->> 'serie' from users;
json_array_elements()仅适用于
json,必须
jsonb_array_elements()适用
jsonb。但是您尝试使用未为定义的
jsonb运算符
@>
json:
groups -> 'data' @> '?'
所述操作者
->将返回相同类型左手输入。但
@>仅针对
jsonb而不是进行定义
json。
然后,您尝试使用运营商
@>的
text左操作数。 也不可能 :
groups ->> 'data' @> ?
运算符
@>有多种变体,可以用于各种类型(包括Postgres数组),但不能用于
text和不能用于
json。
因此,简短的答案:使用
jsonb代替
json。这也允许使用非常 有效的索引 :
json
对于数据类型,
json您可以使用:
SELECt *FROM users uWHERe EXISTS ( SELECt FROM json_array_elements(u.groups) elem WHERe elem ->> 'serie' = '5' );
演示版
jsonb:
SELECt *FROM ( VALUES (1, jsonb '[{"serie":5, "year":3, "specialization":"Matematica", "management_id":1, "group_number":2} , {"serie":5, "year":3, "specialization":"Matematica", "management_id":1, "group_number":2}]') , (2, '[{"serie":7, "year":3, "specialization":"Matematica", "management_id":1, "group_number":2} , {"serie":8, "year":3, "specialization":"Matematica", "management_id":1, "group_number":2}]') , (3, '[{"serie":9, "year":3, "specialization":"Matematica", "management_id":1, "group_number":2} , {"serie":5, "year":3, "specialization":"Matematica", "management_id":1, "group_number":2}]') ) users(id, groups)WHERe groups @> '[{"serie": 5}]';json:
SELECt *FROM ( VALUES (1, json '[{"serie":5, "year":3, "specialization":"Matematica", "management_id":1, "group_number":2} , {"serie":5, "year":3, "specialization":"Matematica", "management_id":1, "group_number":2}]') , (2, '[{"serie":7, "year":3, "specialization":"Matematica", "management_id":1, "group_number":2} , {"serie":8, "year":3, "specialization":"Matematica", "management_id":1, "group_number":2}]') , (3, '[{"serie":9, "year":3, "specialization":"Matematica", "management_id":1, "group_number":2} , {"serie":5, "year":3, "specialization":"Matematica", "management_id":1, "group_number":2}]') ) users(id, groups)WHERe EXISTS ( SELECt FROM json_array_elements(users.groups) elem WHERe elem ->> 'serie' = '5' );


