2016-05-12 55 views
1

我已閱讀文檔和堆棧,但我太愚蠢得到這個沒有問我的具體問題。更新Postgres 9.5 Jsonb通過編號

說我有一個存儲在jsonb列中的對象數組,例如,

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

什麼是改變指數1的從「B」至「C」的值,如果你沒有索引,必須通過ID = 2搜索的最有效方法是什麼?

更具體地說,我正在編寫一個react/redux/node實時應用程序,我不想相信redux狀態以使索引更新值。相反,我希望客戶端發送id = 2並讓服務器/數據庫找到該數組的索引,然後更新該值。我正在使用邏輯來返回索引(例如,選擇整個jsonb列,使用lodash函數來查找id = 2的索引,然後使用lodash找到的索引更新jsonb_set)。

我的希望是有一個查詢,沒有服務器邏輯的方式來實現這一點。我試圖使用子查詢,但postgres文檔不顯示如何返回索引。

感謝您的幫助!

編輯:這裏是當前的數據庫查詢和邏輯使用節點。

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"}]; 
}) 

這可以簡化爲一個postgres查詢嗎?

+0

你的問題並沒有多大感覺:「什麼是最有效的方式......」。你能否提供一個你想要完成的事情,你在做什麼以及爲什麼失敗的例子? –

+0

你如何改變「價值」:「b」爲「價值」:c「當你有id = 2並且沒有索引?我所做的並不是失敗,因此我的問題是」什麼是最有效的方式。 「我的方式可能是唯一的方式,這就是我希望有人能夠回答的問題。 –

回答

3

示例數據:

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"}]'); 

你有兩個選擇。第一個(有點複雜),使用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) 

第二個選項(簡單一點),修改連續JSON元素的值和彙總結果:

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

絕對的天才,謝謝!我發現你的第一個例子更容易一些(可能是因爲這與我試圖寫的查詢類似)。我的問題是假設你知道行ID,只需要添加一個where rowid = –

+0

我需要刪除查詢在這個例子中,id爲相同的數據。 –