PostgreSQL将对象数组转换为对象映射

时间:2020-08-16 14:14:00

标签: sql postgresql jsonb

我在数据库中有一个表,该表的列文本类型为jsonb,如下所示:

{
  "texts": [
    {
      "locale": "ar",
      "textDictionary": {
        "key1": "arabic1",
        "key2": "arabic2"
      }
    },
    {
      "locale": "en",
      "textDictionary": {
        "key1": "english1",
        "key2": "english2"
      }
    }
  ]
}

鉴于上述结构,目标是将该列转换为使用语言环境到字典的映射,而不是语言环境数组,这是为了以更体面的方式支持按语言环境对tsvector进行索引像这样:

CREATE INDEX texts_index ON docs
    USING gin ( to_tsvector('english',texts->'en') );

所需结构:

{
  "ar": {
    "key1": "arabic1",
    "key2": "arabic2"
  },
  "en": {
    "key1": "english1",
    "key2": "english2"
  }
}

任何建议都会很棒!非常感谢你! -无论如何,在PostgreSQL中还是要这样做,还是应该在应用程序级别完成?

2 个答案:

答案 0 :(得分:2)

您可以通过取消嵌套并聚合回去来进行转换:

select id, jsonb_object_agg(x.e ->> 'locale', x.e -> 'textDictionary')
from data d
  cross join jsonb_array_elements(d.texts -> 'texts') as x(e)
group by id;

这可用于UPDATE语句:

update data
  set texts = t.new_texts
from (  
  select id, jsonb_object_agg(x.e ->> 'locale', x.e -> 'textDictionary') as new_texts
  from data d
    cross join jsonb_array_elements(d.texts -> 'texts') as x(e)
  group by id
) t
where t.id = data.id;

答案 1 :(得分:1)

您可以尝试以下方法:

update docs 
 set texts= (
            select jsonb_object_agg(j->>'locale',j->'textDictionary') 
            from 
            jsonb_array_elements(texts->'texts') j
            ) 

DEMO