Как обновить значение во вложенных json Postgres

#sql #postgresql #jsonb

#sql #postgresql #jsonb

Вопрос:

У меня есть следующий JSON, сохраненный в столбце «Информация»

 {
  "customConfig": {
    "isCustomGoods": 1
  },
  "new_addfields": {
    "data": [
      {
        "val": {
          "items": [
            {
              "Code": "calorie",
              "Value": "365.76"
            },
            {
              "Code": "protein",
              "Value": "29.02"
            },
            {
              "Code": "fat",
              "Value": "23.55"
            },
            {
              "Code": "carbohydrate",
              "Value": "6.02"
            },
            {
              "Code": "spirit",
              "Value": "1.95"
            }
          ],
          "storageConditions": "",
          "outQuantity": "100"
        },
        "parameterType": "Nutrition",
        "name": "00000000-0000-0000-0000-000000000001",
        "label": "1"
      },
      {
        "name": "b4589168-5235-4ec5-bcc7-07d4431d14d6_Для ресторанов",
        "val": "true"
      }
    ]
  }
}
  

Я хочу обновить значение вложенного json

 {
  "name": "b4589168-5235-4ec5-bcc7-07d4431d14d6_Для ресторанов",
  "val": "true"
}
  

и установите «val» на «Yes» str, чтобы результат был таким

 {
  "name": "b4589168-5235-4ec5-bcc7-07d4431d14d6_Для ресторанов",
  "val": "Yes"
}
  

Как я могу это сделать? Предполагая, что мне нужно обновить это значение в json для многих записей в базе данных

Комментарии:

1. Является ли ваша структура JSON фиксированной или ее можно изменить

Ответ №1:

Учитывая, что у вас есть постоянная структура JSON и первичный ключ в вашей таблице.Идея состоит в том, чтобы получить точный путь к элементу val , имеющему значение true (которое может быть с любым индексом в массиве), а затем заменить его на желаемое значение. Итак, вы можете написать свой запрос, как показано ниже:

 with cte as (
select 
  id, 
  ('{new_addfields,data,'||index-1||',val}')::text[] as json_path
from 
  test, 
  jsonb_array_elements(info->'new_addfields'->'data') 
  with ordinality arr(vals,index) 
where 
  arr.vals->>'val' ilike 'true'
  )

 update test 
 set info = jsonb_set(info,cte.json_path,'"Yes"',false) 
 from cte 
 where test.id=cte.id;

  

ДЕМОНСТРАЦИЯ

Ответ №2:

Мы можем использовать jsonb_set() то, что доступно из Postgres 9.5

Из документов:

 jsonb_set(target jsonb, path text[], new_value jsonb [, create_missing boolean])
  

Запрос для обновления вложенного объекта:

 UPDATE temp t
SET info = jsonb_set(t.info,'{new_addfields,data,1,val}', jsonb '"Yes"')
where id = 1;
  

Его также можно использовать в запросе select:

 SELECT 
  jsonb_set(t.info,'{new_addfields,data,1,val}', jsonb '"Yes"')
FROM temp t
LIMIT 1;