2014-05-18 31 views
11

我想在Postgresql 9.4中访问一个嵌套的jsonb字段。但是我很难根据嵌套的jsonb值检索记录。有没有人有过这个成功?如何在Postgresql 9.4中访问嵌套的JSON?

  • 首先,我创建的表:

    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

我可能已经想通了。根据OP中的表,以下2个查询正确返回记录: (1)SELECT * FROM Meal WHERE recipe @>'{“meal':[{”calories“:900}]}':: jsonb ; (2)SELECT * FROM Meal WHERE recipe @>'{“meal':[{”calories“:900}]}':: jsonb AND recipe @>'{'meal':[{”fruit“:[{{ “ID”:4}]}]}':: jsonb; 并且下面的查询不会返回记录(这是因为meal.fruit.id = 40不存在是正确的): (3)SELECT * FROM Meal WHERE recipe @>'{“meal”:[{“calories “:900}]}':: jsonb AND recipe @>'{”meal“:[{”fruit“:[{”id“:40}]}]}':: jsonb; 希望这有助于! – bjones1831

+1

在测试版发布时间不到72小时的情况下提出一个新功能问题,如果有的话,不会在SO上产生许多明智的答案。在这种情况下的问题最好在postgresql的邮件列表中问一下, - 黑客想起来了。 – Patrick

回答

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类似的比较语义,而不是依赖于上面的转换。

+0

我将这个标记为答案,因为它可以工作,并且...它还帮助我在比较中使用jsonb值(例如,调整craig从“= 900”到“> 900”的查询不会返回记录。这是正确的...感谢您的帮助!我一直在努力弄清今天大部分时间的比较情况。 – bjones1831

+0

在PostgreSQL 9.5上,您可以按照以下所述使用@>运算符:http://stackoverflow.com/questions/28486192/postgresql-query-array-of-objects-in-jsonb-field –