2016-05-12 54 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为相同的数据。 –