доступ к списку из json и повторение в postgres - PullRequest
0 голосов
/ 30 мая 2018

У меня есть json, как упомянуто ниже,

{
    "list": [{
            "notificationId": 123,
            "userId": 444
        },
        {
            "notificationId": 456,
            "userId": 789
        }
    ]
}

Мне нужно написать процедуру postgres, которая просматривает список и выполняет обновление / вставку на основе уже существующего идентификатора уведомления или его отсутствия в БД.

У меня есть таблица уведомлений, в которой столбцы уведомлений и ИД пользователей указаны в виде столбцов.

Может кто-нибудь подсказать, как это сделать с помощью операторов postgres json.

Ответы [ 3 ]

0 голосов
/ 30 мая 2018

Предполагая, что у вас есть уникальное ограничение на notificationid (например, поскольку это первичный ключ, нет необходимости в сохраненной функции или цикле:

with data (j) as (
  values ('
  {
      "list": [{
              "notificationId": 123,
              "userId": 444
          },
          {
              "notificationId": 456,
              "userId": 789
          }
      ]
  }'::jsonb)
)
insert into notification (notificationid, userid)
select (e.r ->> 'notificationId')::int, (e.r ->> 'userId')::int
from data d, jsonb_array_elements(d.j -> 'list') as e(r)
on conflict (notificationid) do update
   set userid = excluded.userid;

Первым шагом в этом операторе является поворотмассив в список строк, это то, что:

select e.*
from data d, jsonb_array_elements(d.j -> 'list') as e(r)

делает. Учитывая ваш пример JSON, это возвращает две строки со значением JSON в каждой:

r                                     
--------------------------------------
{"userId": 444, "notificationId": 123}
{"userId": 789, "notificationId": 456}

Это тогдаразделить на два целочисленных столбца:

select (e.r ->> 'notificationId')::int, (e.r ->> 'userId')::int
from data d, jsonb_array_elements(d.j -> 'list') as e(r)

Итак, мы получим:

int4 | int4
-----+-----
 123 |  444
 456 |  789

И этот результат используется в качестве входных данных для оператора INSERT.

Затем предложение on conflict выполняет вставку или обновление в зависимости от наличия строки, идентифицируемой столбцом notificationid, который должен иметь уникальный индекс.

0 голосов
/ 30 мая 2018

Тем временем я попробовал это,

CREATE OR REPLACE FUNCTION insert_update_notifications(notification_ids jsonb) RETURNS void AS
$$
DECLARE
allNotificationIds text[];
indJson jsonb;
notIdCount int;
i json;
BEGIN

FOR i IN SELECT * FROM jsonb_array_elements(notification_ids)
  LOOP
    select into notIdCount count(notification_id) from notification_table where notification_id = i->>'notificationId' ;
    IF(notIdCount = 0 ) THEN
       insert into notification_table(notification_id,userid) values(i->>'notificationId',i->>'userId');
    ELSE
        update notification_table set userid = i->>'userId' where notification_id = i->>'notificationId';
    END IF;
  END LOOP;

END;
$$
language plpgsql;

select * from insert_update_notifications('[{
        "notificationId": "123",
        "userId": "444"
    },
    {
        "notificationId": "456",
        "userId": "789"
    }
]');

Это работает .. Пожалуйста, просмотрите это.

0 голосов
/ 30 мая 2018

Попробуйте этот запрос:

SELECT *
FROM yourTable
WHERE col->'list'@>'[{"notificationId":123}]';

Вы можете заменить значение 123 на любое notificationId, которое вы хотите найти.Перейдите по ссылке ниже для демонстрации, показывающей, как работает эта логика:

Демо

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