如何在Postgresql 9.4中访问嵌套的JSON?

bjo*_*831 12 postgresql json

我正在尝试访问Postgresql 9.4中的嵌套jsonb字段.但是我很难根据嵌套的jsonb值检索记录.有人有这个成功吗?

  • 首先,我创建了表:

    CREATE TABLE Meal (
        id INT
      , recipe JSONB
    );
    
    Run Code Online (Sandbox Code Playgroud)
  • 其次,我将以下记录插入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}]
     }]
    }');
    
    Run Code Online (Sandbox Code Playgroud)
  • 第三,我尝试了以下查询来根据卡路里计数检索此记录(其中没有一个是有效的):

这些返回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';
Run Code Online (Sandbox Code Playgroud)

这些导致失败(语法不正确):

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';
Run Code Online (Sandbox Code Playgroud)

如果您有任何建议,我将非常感谢听到他们.

Cra*_*ger 14

选择餐:

select * from meal where recipe #>> '{meal,0,calories}' = '900';
Run Code Online (Sandbox Code Playgroud)

如果要在数组中找到这些条目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;
Run Code Online (Sandbox Code Playgroud)

json功能的一些可能的未来增强将使这更容易.支持通配符的路径搜索功能可以返回一个集合将非常有用 - 可能作为增强功能json_extract_path.也许在9.5如果有人证明渴望.另一件真正有帮助的事情是转换函数或json标量的转换,所以我们可以编写recipe_entry -> 'calories' = to_json(900)并获得类似Javascript的相等比较语义,而不是依赖于上面的转换.