2016-11-15 28 views
0

如何根據對象的某個鍵的值從數組中刪除對象?如何刪除基於嵌套鍵值的JSONB列中的數組元素?

該數組嵌套在父對象中。

下面是一個示例結構:

{ 
    "foo1": [ { "bar1": 123, "bar2": 456 }, { "bar1": 789, "bar2": 42 } ], 
    "foo2": [ "some other stuff" ] 
} 

我可以刪除基於的bar1的值的數組元素?

我可以查詢基於使用bar1值:columnname @> '{ "foo1": [ { "bar1": 123 } ]}',但我沒有運氣找到一種方法,同時保持一切完好無損從foo1刪除{ "bar1": 123, "bar2": 456 }

感謝


運行的PostgreSQL 9.6

回答

2

假設你要搜索特定的對象具有一定價值的內部對象,此特定對象可以在陣列中的任何地方出現,您需要解壓縮文檔和每個陣列,測試內部子文檔以進行控制並刪除,然後重新組裝陣列和JSON文檔(未經測試):

SELECT id, jsonb_build_object(key, jarray) 
FROM (
    SELECT foo.id, foo.key, jsonb_build_array(bar.value) AS jarray 
    FROM ( SELECT id, key, value 
      FROM my_table, jsonb_each(jdoc)) foo, 
     jsonb_array_elements(foo.value) AS bar (value) 
    WHERE NOT bar.value @> '{"bar1": 123}'::jsonb 
    GROUP BY 1, 2) x 
GROUP BY 1; 
現在

,這看起來可能有點晦澀難懂,所以百般挑剔你:

SELECT id, key, value 
FROM my_table, jsonb_each(jdoc) 

這將使用你的桌子上的橫向聯接採取JSON文件jdoc並把它變成一組行foo(id, key, value)其中value包含數組。 id是您的表的主鍵。

然後我們得到:

SELECT foo.id, foo.key, jsonb_build_array(bar.value) AS jarray 
FROM foo, -- abbreviated from above 
    jsonb_array_elements(foo.value) AS bar (value) 
WHERE NOT bar.value @> '{"bar1": 123}'::jsonb 
GROUP BY 1, 2 

這將使用另一種橫向連接到陣列解壓到bar(value)行。現在可以使用包含運算符搜索這些對象以從結果集中刪除對象:WHERE NOT bar.value @> '{"bar1": 123}'::jsonb。在選擇列表中,陣列由idkey重新組裝,但現在沒有違規的子文檔。

最後,在主查詢的JSON文件重新組裝:

SELECT id, jsonb_build_object(key, jarray) 
FROM x -- from above 
GROUP BY 1; 

瞭解的重要一點是,PostgreSQL的JSON功能只在JSON文件,你可以明確地指示的水平運行。通常,這是文檔的頂層,除非您在文檔中具有某個級別的明確路徑(如{foo1, 0, bar1},但您沒有)。在這個級別的操作中,您可以解壓縮以執行處理,例如移除對象。