postgres как добавить значение в массив, если хранить в поле json - PullRequest
1 голос
/ 09 января 2020
{
    "title": "new abc",
    "genres": ["Fiction", "Thriller", "Horror"],
    "published": false
}

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

1 Ответ

1 голос
/ 09 января 2020

jsonb_insert может быть тем, что вы ищете.

Из документации

jsonb_insert(target jsonb, path text[], new_value jsonb [, insert_after boolean])

Возвращает цель со вставленным new_value. Если целевой раздел, обозначенный путем, находится в массиве JSONB, new_value будет вставлено до цели или после, если insert_after равен true (по умолчанию false). Если целевой раздел, обозначенный путем, находится в объекте JSONB, new_value будет вставлено, только если целевой объект не существует. Как и в случае с ориентированными на путь операторами, отрицательные целые числа, которые появляются в пути, считаются с конца JSON массивов.

Этот запрос вставляет в массив genres новый элемент с именем Comedy в начале массива - проверено на PostgreSQL 10.10:

SELECT jsonb_insert('{"title": "new abc",
                      "genres": ["Fiction", "Thriller", "Horror"],
                      "published": false}','{genres,0}','"Comedy"',false);

                                          jsonb_insert                                           
-------------------------------------------------------------------------------------------------
 {"title": "new abc", "genres": ["Comedy", "Fiction", "Thriller", "Horror"], "published": false}
(1 Zeile)

Редактировать : проверка наличия элемента внутри массива перед его вставкой - см. комментарии:

Пример данных

CREATE TEMPORARY TABLE t (f jsonb);
INSERT INTO t VALUES ('{"title": "new abc",
                      "genres": ["Fiction", "Thriller", "Horror"],
                      "published": false}');

Запрос - несуществующий элемент

SELECT jsonb_insert(f,'{genres,0}','"Comedy"',false) 
FROM t
WHERE '"Comedy"' NOT IN 
  (SELECT * FROM jsonb_array_elements(f#>'{genres}'));

-------------------------------------------------------------------------------------------------
 {"title": "new abc", "genres": ["Comedy", "Fiction", "Thriller", "Horror"], "published": false}
(1 Zeile)

Запрос - существующий элемент

SELECT jsonb_insert(f,'{genres,0}','"Fiction"',false) 
FROM t
WHERE '"Fiction"' NOT IN 
  (SELECT * FROM jsonb_array_elements(f#>'{genres}'));

 jsonb_insert 
--------------
(0 Zeilen)
...