我试图访问Postgresql 9.4中的嵌套jsonb字段。但是我很难根据嵌套的jsonb值检索记录。有人有这个成功吗?
首先,我创建了表格:
CREATE TABLE Meal (
id INT
, recipe JSONB
);
其次,我将以下记录插入dbo.Meal: (我通过jsonlint.com运行json,它返回有效)
INSERT INTO Meal (id, recipe)
VALUES (
1,
'{
"meal": [{
"calories" : 900,
"serves" : [{"min": 2, "max": 4}],
"fruit" : [{"id": 1, "qty": 2}, {"id": 4, "qty": 3}],
"veggie" : [{"id": 4, "qty": 1}, {"id": 2, "qty": 10}]
}]
}');
第三,我尝试了以下查询,根据卡路里计数检索此记录(其中没有一个是有效的):
这些返回0记录:
SELECT * FROM Meal ...
WHERE recipe::json#>>'{meal, calories}' = '900';
WHERE recipe::json->>'{meal, calories}' = '900';
WHERE recipe::json->>'meal[calories]' = '900';
WHERE recipe::json->>'{meal[calories]}' = '900';
WHERE recipe::json#>>'{meal[calories]}' = '900';
WHERE recipe::json#>>'{meal.calories}' = '900';
WHERE recipe::json->>'{meal.calories}' = '900';
WHERE recipe::jsonb#>>'{meal, calories}' = '900';
WHERE recipe::jsonb->>'{meal, calories}' = '900';
WHERE recipe::jsonb#>>'{meal[calories]}' = '900';
WHERE recipe::jsonb->>'{meal[calories]}' = '900';
WHERE recipe::jsonb->>'meal[calories]' = '900';
WHERE recipe::jsonb#>'{meal, calories}' = '900';
WHERE recipe::jsonb->'{meal, calories}' = '900';
WHERE recipe::jsonb->'meal[calories]' = '900';
WHERE recipe::jsonb#>'{meal[calories]}' = '900';
WHERE recipe::jsonb->'{meal[calories]}' = '900';
WHERE recipe::jsonb#>>'{meal.calories}' = '900';
WHERE recipe::jsonb#>'{meal.calories}' = '900';
WHERE recipe::jsonb->>'{meal.calories}' = '900';
WHERE recipe::jsonb->'{meal.calories}' = '900';
导致失败(语法不正确):
SELECT * FROM Meal ...
WHERE recipe::json#>'{meal, calories}' = '900';
WHERE recipe::json->'{meal, calories}' = '900';
WHERE recipe::json#>>'meal[calories]' = '900';
WHERE recipe::json#>'meal[calories]' = '900';
WHERE recipe::json->'meal[calories]' = '900';
WHERE recipe::json#>'{meal[calories]}' = '900';
WHERE recipe::json->'{meal[calories]}' = '900';
WHERE recipe::json#>'{meal.calories}' = '900';
WHERE recipe::json->'{meal.calories}' = '900';
WHERE recipe::jsonb#>>'meal[calories]' = '900';
WHERE recipe::jsonb#>'meal[calories]' = '900';
如果您有任何建议,我将非常感谢您的聆听。
答案 0 :(得分:13)
选择餐点:
select * from meal where recipe #>> '{meal,0,calories}' = '900';
如果要在数组meal
中找到这些条目,则必须迭代数组以检查每个键。没有通配符数组索引或对象名称占位符 - 您不能写{meal,*,calories}
。反正还没有; json功能不断改进。
以下是我的表现:
select meal.id, recipe_entry
from meal,
lateral jsonb_array_elements(recipe -> 'meal') recipe_entry
where CAST(recipe_entry ->> 'calories' AS integer) = 900;
json功能的一些未来可能的增强将使这更容易。支持通配符的路径搜索功能可以返回一个集合非常有用 - 可能是json_extract_path
的增强功能。也许在9.5如果有人证明渴望。另一件真正有帮助的事情是json标量的转换函数或强制转换,因此我们可以编写recipe_entry -> 'calories' = to_json(900)
并获得类似Javascript的等式比较语义,而不是依赖于上面的强制转换。