2014-05-18 32 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 –