Запрос на обновление значения JSON - PullRequest
1 голос
/ 27 апреля 2020

Я хочу запросить обновление таблицы, содержащей JSON данных. Данные столбца detail в таблице details следующие:

id     | 1

detail | {
   myCompany: [{ email: 'company@company.com', inProfit: true }],
   myData: [
      { email: 'example@example.com'},
      { email: 'test@test.com'},
      { email: 'test@example.com' },
   ],
};

Значение JSON столбца подробно выглядит следующим образом

{
   "myCompany":[
      {
         "email":"company@company.com",
         "inProfit":true
      }
   ],
   "myData":[
      {
         "email":"example@example.com"
      },
      {
         "email":"test@test.com"
      },
      {
         "email":"test@example.com",
      }
   ]
} 

Я хочу запрос, который обновляет myData. Добавьте новое поле personalUse:true для всех полей myData после email. Например, после выполнения запроса на обновление поле myData должно выглядеть следующим образом:

"myData":[
      {
         "email":"example@example.com",
         "personalUse":true
      },
      {
         "email":"test@test.com",
         "personalUse":true
      },
      {
         "email":"test@example.com",
         "personalUse":true
      }
   ]

Вы можете использовать приведенные ниже запросы, чтобы попробовать его локально.

CREATE TABLE details (id bigserial primary key, detail json not null);

INSERT INTO details (detail) 
VALUES 
  ('{"myCompany":[{"email":"company@company.com", "inProfit":true } ],  
     "myData":[{"email":"example@example.com" }, 
               {"email":"test@test.com"},
               {"email":"test@example.com"} ] }');

Пожалуйста, кто-нибудь, помогите мне.

1 Ответ

1 голос
/ 27 апреля 2020

Есть несколько функций, которые могут быть полезны:

  • -> оператор: получает JSON поле объекта по ключу.
  • jsonb_agg: агрегирует значения как JSON массив.
  • json_array_elements: расширяет массив JSON до набора JSON значений.
  • jsonb_set: заменяет часть JSON, обозначенную путем, на значение (или вставьте его, если деталь отсутствует).

Подробнее читайте здесь:

Запрос

update details
  set detail = jsonb_set(detail::jsonb, '{myData}', myData)
  from (
    select id, jsonb_agg(myData) as myData
      from (
        select
          id,
          jsonb_set(
            json_array_elements(detail->'myData')::jsonb,
            '{personalUse}',
            'true') as myData
          from details
      ) x
      group by id
  ) z
  where details.id = z.id;

Как это работает

Расширение myData массивов вместе с id в таблицу.

user=# select id, json_array_elements(detail->'myData') as myData from details;
 id |                        mydata                         
----+-------------------------------------------------------
  1 | {"email": "example@example.com"}
  1 | {"email": "test@test.com"}
  1 | {"email": "test@example.com"}
  2 | {"email": "tt@test.com"}
  2 | {"email": "tt@example.com"}

Используйте jsonb_set для обновления каждого объекта.

user=# select
user-#   id,
user-#   jsonb_set(
user(#     json_array_elements(detail->'myData')::jsonb,
user(#     '{personalUse}',
user(#     'true'
user(#   ) as myData
user-# from details;
 id |                        mydata                         
----+-------------------------------------------------------
  1 | {"email": "example@example.com", "personalUse": true}
  1 | {"email": "test@test.com", "personalUse": true}
  1 | {"email": "test@example.com", "personalUse": true}
  2 | {"email": "tt@test.com", "personalUse": true}
  2 | {"email": "tt@example.com", "personalUse": true}

Используйте jsonb_agg для сбора сообщений обратно в массив JSON.

user=# select id, jsonb_agg(myData) as myData from (
user(#   select
user(#     id,
user(#     jsonb_set(
user(#       json_array_elements(detail->'myData')::jsonb,
user(#       '{personalUse}',
user(#       'true'
user(#     ) as myData
user(#   from details
user(# ) x group by id;
 id |
----+-------------------------------------------------------------
  2 | [{"email": "tt@test.com", "personalUse": true}, ...
  1 | [{"email": "example@example.com", "personalUse": true}, ...

Теперь вы можете снова использовать jsonb_set для обновления оригинала JSON.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...