我正在尝试查询Postgres数据库中的某个值。我在Int
表中有一个名为groups
的字段,可以用以下任何一种方式表示:
1
users
2
groups: {"data"=>[{"serie"=>5, "year"=>3, "specialization"=>"Matematica", "management_id"=>1, "group_number"=>2}, {"serie"=>5, "year"=>3, "specialization"=>"Matematica", "management_id"=>1, "group_number"=>2}]}
我对这两种表述都很好。但是,我似乎无法找到如何让所有在系列5中的用户让我们说。我尝试了多个查询:
groups: [{"serie"=>5, "year"=>3, "specialization"=>"Matematica", "management_id"=>1, "group_number"=>2}, {"serie"=>5, "year"=>3, "specialization"=>"Matematica", "management_id"=>1, "group_number"=>2}]
还有许多其他尝试,有些比其他尝试更愚蠢(见上文)。我该怎么做?
我能够确定:
@users = User.where("groups ->> 'data' @> ?", {serie: 5})
@users = User.where("groups -> 'data' @> '?'", {serie: 5})
@users = User.where("groups ->> 'data' ->> 'serie' = ?", 5)
但是以下查询有效:
select groups -> 'data' ->> 'serie' from users;
ERROR: cannot extract field from a non-object.
我认为我没有在列中正确传递数据。我提供的哈希是:
select json_array_elements(groups -> 'data') ->> 'serie' from users;
在保存资源之前,如下所示:
pry(#<Overrides::RegistrationsController>)> @response['data']['user']
=> {"last_name"=>"Doe1",
"first_name"=>"John1",
"email"=>"c0f45@example.com",
"groups"=>
{"data"=>
[{"serie"=>5, "year"=>3, "specialization"=>"Matematica", "management_id"=>1, "group_number"=>2}, {"serie"=>5, "year"=>3, "specialization"=>"Matematica", "management_id"=>1, "group_number"=>2}]}}
答案 0 :(得分:10)
<强>假设:强>
{"serie": 5}
的数组元素。可能还有其他人。&#34; 简短回答:使用 jsonb
代替json
,这只是有效:
User.where("groups @> ?", '[{"serie": 5}]')
注意方括号使右手操作数成为JSON 数组。
这里突出的误解:data type json
is not the same as jsonb
。
您没有声明实际的表定义,但您后来评论了json
并且问题中有一个提示:
select json_array_elements(groups -> 'data') ->> 'serie' from users;
json_array_elements()
仅适用于json
,jsonb_array_elements()
必须jsonb
。
但是您尝试使用jsonb
Operators @>
,json
:
groups -> 'data' @> '?'
operator ->
返回与左侧输入相同的类型。但@>
仅为jsonb
定义,而不是json
。
然后,您尝试将@>
的运算符text
用作左侧操作数。 不可能:
groups ->> 'data' @> ?
对于各种类型(包括Postgres数组),运算符@>
有变体,但不适用于text
而不适用于json
。
简而言之:使用jsonb
代替json
。这也允许使用非常高效索引:
json
对于数据类型json
,您可以使用:
SELECT *
FROM users u
WHERE EXISTS (
SELECT 1
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 1
FROM json_array_elements(users.groups) elem
WHERE elem ->> 'serie' = '5'
);