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

时间:2014-05-18 05:52:15

标签: json postgresql

我试图访问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';

如果您有任何建议,我将非常感谢您的聆听。

1 个答案:

答案 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的等式比较语义,而不是依赖于上面的强制转换。