2016-05-12 7 views
1

Ich habe die Dokumente und Stapel gelesen, aber ich bin zu dumm, um dies zu bekommen, ohne meine spezifische Frage zu stellen.Aktualisierung Postgres 9.5 Jsonb von ID

Angenommen, ich habe ein Array von Objekten in einer JSONB-Spalte gespeichert, z.

[{"id":1, "value":"a"], {"id":2, "value":"b"}] 

Was ist der effizienteste Weg, Index 1 den Wert von „b“ bis „c“ zu ändern, wenn Sie den Index nicht haben und von id = 2 suchen muss?

Um genauer zu sein, schreibe ich eine React/Redux/Node Echtzeit-App, und ich möchte nicht den Redux-Status vertrauen, um den Index zu aktualisieren Wert geben. Stattdessen möchte ich, dass der Client id = 2 sendet und der Server/Datenbank den Index dieses Arrays findet und den Wert aktualisiert.

Ich verwende derzeit Logik, um den Index zurückzugeben (z. B. die gesamte jsonb-Spalte auswählen, eine lodash-Funktion verwenden, um den Index mit id = 2 zu finden, dann jsonb_set mit dem lodash found index aktualisieren).

Ich hoffe, es gibt eine einzige Abfrage, keine Serverlogik, um dies zu erreichen. Ich habe versucht, Unterabfragen zu verwenden, aber die Postgres-Dokumente zeigen nicht, wie ein Index zurückgegeben wird.

Danke für die Hilfe!

EDIT: Hier ist die aktuelle Datenbank Abfragen und Logik mit Knoten.

let _ = require('lodash'); 
let id=2; 
let newValue='c'; 
let query=`SELECT jsonb_column from table where rowid=1`; 
pgQuery(query) 
.then((result)=>{ 
    result=result[0].result // cleaning up the return object 
    //result=[{"id":1, "value":"a"], {"id":2, "value":"b"}]; 
    let index=_.findLastIndex(result, {id}) // index=1 
    let query2=`UPDATE table 
       SET jsonb_column=jsonb_set(jsonb_column, '{${index}, value}', '${newValue}') 
       WHERE rowid=1` RETURNING jsonb_column 

    return pgQuery(query2) 
    // returns [{"id":1, "value":"a"], {"id":2, "value":"c"}]; 
}) 

Kann das auf eine Postgres-Abfrage reduziert werden?

+0

Ihre Frage nicht viel machen Sinn: "Was ist der effizienteste Weg ...". Können Sie ein Beispiel dafür nennen, was Sie erreichen wollen, was Sie tun und warum es scheitert? –

+0

Wie änderst du "value": "b" in "value": c "wenn du id = 2 und keinen Index hast? Was ich mache ist nicht scheitern, also meine Frage" was ist der effizienteste Weg. "Mein Weg ist vielleicht der einzige Weg. Das ist, was ich hoffe, dass jemand antworten kann. –

Antwort

3

Beispieldaten:

create table a_table (rowid int, jsonb_column jsonb); 
insert into a_table values (1, '[{"id":1, "value":"a"}, {"id":2, "value":"b"}]'); 
insert into a_table values (2, '[{"id":2, "value":"a"}, {"id":1, "value":"b"}]'); 

Sie haben zwei Möglichkeiten. Die erste (etwas kompliziert), verwenden jsonb_array_elements(jsonb_column) with ordinality:

update a_table t1 
set jsonb_column = 
     jsonb_set(
      jsonb_column, 
      array[(
       select ordinality::int- 1 
       from a_table t2, jsonb_array_elements(jsonb_column) with ordinality 
       where t1.rowid = t2.rowid and value->>'id' = '2')::text, 
      'value'::text], 
      '"c"' 
     ); 

select * from a_table; 

rowid |     jsonb_column      
-------+---------------------------------------------------- 
    1 | [{"id": 1, "value": "a"}, {"id": 2, "value": "c"}] 
    2 | [{"id": 2, "value": "c"}, {"id": 1, "value": "b"}] 
(2 rows) 

Die zweite Option (etwas einfacher), ändern Werte in aufeinanderfolgenden json Elementen und aggregieren das Ergebnis:

update a_table t1 
set jsonb_column = (
    select jsonb_agg(val) 
    from (
     select case 
      when value->'id' = '2' then jsonb_set(value, '{value}', '"d"') 
      else value end val 
     from a_table t2, jsonb_array_elements(jsonb_column) 
     where t1.rowid = t2.rowid 
     ) s 
    ); 

select * from a_table; 

rowid |     jsonb_column      
-------+---------------------------------------------------- 
    1 | [{"id": 1, "value": "a"}, {"id": 2, "value": "d"}] 
    2 | [{"id": 2, "value": "d"}, {"id": 1, "value": "b"}] 
(2 rows) 
+0

Absolut genial, danke! Ich fand dein erstes Beispiel ein wenig einfacher (wahrscheinlich weil das der Abfrage ähnlich ist, die ich versuchte zu schreiben) ein paar Nachforschungen über die Ordinalität und für jeden anderen, der meine Frage und die Antwort betrachtet, beantwortet Klin eine schwierigere Frage, alle Zeilen zu ändern.Meine Frage geht davon aus, dass Sie die Zeilen-ID kennen.Fügen Sie einfach eine Zeile hinzu: rowid = –

+0

Ich brauche eine Abfrage löschen id für gleiche Daten in diesem Beispiel. –

Verwandte Themen