2016-08-17 39 views
6

目前我正在使用postgreSQL 9.5並嘗試更新jsonb字段數組內的值。但我無法得到所選擇的值的指數postgresql 9.5 jsonb_set獲取json數組的索引

我的表看起來就像:

CREATE TABLE samples (
    id serial, 
    sample jsonb 
); 

我的JSON的樣子:

{"result": [ 
    {"8410": "ABNDAT", "8411": "Abnahmedatum"}, 
    {"8410": "ABNZIT", "8411": "Abnahmezeit"}, 
    {"8410": "FERR_R", "8411": "Ferritin"} 
]} 

我的SELECT語句,以獲得正確的價值的作品:

SELECT 
    id, value 
FROM 
    samples s, jsonb_array_elements(s.sample#>'{result}') r 
WHERE 
    s.id = 26 and r->>'8410' = 'FERR_R'; 

結果:

id | value 
---------------------------------------------- 
26 | {"8410": "FERR_R", "8411": "Ferritin"} 

好的,這是我想要的。現在,我想用下面的UPDATE語句來添加新元素「ratingtext」執行更新(如果尚未有):

UPDATE 
    samples s 
SET 
    sample = jsonb_set(sample, 
       '{result,2,ratingtext}', 
       '"Some individual text"'::jsonb, 
       true) 
WHERE 
     s.id = 26; 

執行UPDATE語句之後,我的數據是這樣的(也是正確的):

{"result": [ 
    {"8410": "ABNDAT", "8411": "Abnahmedatum"}, 
    {"8410": "ABNZIT", "8411": "Abnahmezeit"}, 
    {"8410": "FERR_R", "8411": "Ferritin", "ratingtext": "Some individual text"} 
]} 

到目前爲止好,但我手動搜索的2索引值來獲得JSON數組中的元素的權利。如果訂單將改變,這將無法正常工作。

所以我的問題:

有沒有辦法讓選定的JSON數組元素的索引並結合SELECT語句和UPDATE語句轉換成一個?

就像:

UPDATE 
    samples s 
SET 
    sample = jsonb_set(sample, 
       '{result,' || INDEX OF ELEMENT || ',ratingtext}', 
       '"Some individual text"'::jsonb, 
       true) 
WHERE 
     s.id = 26; 

準備語句之前已知的的samples.id「8410」值。

或者目前這是不可能的?

回答

7

,可以看到使用jsonb_array_elements() with ordinality一個搜索到的元素的索引(注意,從1 ordinality開始而JSON陣列的第一索引是0):

select 
    pos- 1 as elem_index 
from 
    samples, 
    jsonb_array_elements(sample->'result') with ordinality arr(elem, pos) 
where 
    id = 26 and 
    elem->>'8410' = 'FERR_R'; 

elem_index 
------------ 
      2 
(1 row) 

使用上面的查詢來更新基於所述元件它的索引(注意,jsonb_set()第二個參數是一個文本陣列):

update 
    samples 
set 
    sample = 
     jsonb_set(
      sample, 
      array['result', elem_index::text, 'ratingtext'], 
      '"some individual text"'::jsonb, 
      true) 
from (
    select 
     pos- 1 as elem_index 
    from 
     samples, 
     jsonb_array_elements(sample->'result') with ordinality arr(elem, pos) 
    where 
     id = 26 and 
     elem->>'8410' = 'FERR_R' 
    ) sub 
where 
    id = 26;  

結果:

select id, jsonb_pretty(sample) 
from samples; 

id |     jsonb_pretty     
----+-------------------------------------------------- 
26 | {            + 
    |  "result": [         + 
    |   {          + 
    |    "8410": "ABNDAT",     + 
    |    "8411": "Abnahmedatum"    + 
    |   },          + 
    |   {          + 
    |    "8410": "ABNZIT",     + 
    |    "8411": "Abnahmezeit"    + 
    |   },          + 
    |   {          + 
    |    "8410": "FERR_R",     + 
    |    "8411": "Ferritin",     + 
    |    "ratingtext": "Some individual text"+ 
    |   }          + 
    |  ]           + 
    | } 
(1 row) 
+0

非常感謝您的回答!它就像一個魅力!我沒有意識到,我可以在WHERE子句中使用** elem **。 –

+0

謝謝klin,這只是拯救了我的一天! –