2016-08-17 19 views
6

Obecnie pracuję z postgreSQL 9.5 i próbuję zaktualizować wartość wewnątrz tablicy pola jsonb. Ale nie jestem w stanie uzyskać indeks wybranej wartościPostgresql 9.5 jsonb_set uzyskiwanie indeksu tablicy json

Moja tabela właśnie wygląda:

CREATE TABLE samples (
    id serial, 
    sample jsonb 
); 

Moje JSON wygląda następująco:

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

My SELECT, aby uzyskać poprawne prace wartości :

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

wyniki w:

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

OK, tego właśnie chciałem. Teraz chcę, aby wykonać aktualizację za pomocą poniższej instrukcji UPDATE, aby dodać nowy element „ratingtext” (jeśli jeszcze nie istnieje):

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

Po wykonać instrukcję UPDATE, moje dane wygląda następująco (również poprawne):

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

Jak na razie dobrze, ale ręcznie szukana wartość indeksu 2, aby uzyskać prawo wewnątrz elementu tablicy JSON. Jeśli zamówienie zostanie zmienione, nie zadziała.

Więc mój problem:

Czy istnieje sposób, aby uzyskać indeks wybranego elementu tablicy JSON i połączyć SELECT i UPDATE na jeden?

Podobnie jak:

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

Wartości samples.id i "8410" są znane przed przygotowaniem oświadczenie.

A może nie jest to obecnie możliwe?

Odpowiedz

7

można znaleźć indeks szukanego elementu przy użyciu jsonb_array_elements() with ordinality (uwaga, ordinality rozpoczyna się od 1, podczas gdy pierwszy indeks tablicy json jest 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) 

pomocą powyższej kwerendy zaktualizować element oparty na jego indeks (zauważ, że drugi argument jsonb_set() jest tablica tekst):

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;  

Wynik:

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

Dziękuję bardzo za odpowiedź! Działa jak czarujący! Nie zdawałem sobie sprawy, że mogę użyć ** elem ** w klauzuli WHERE. –

+0

Dzięki klin, to właśnie uratowało mój dzień! –

Powiązane problemy