Postgres массив пользовательских типов - как сделать запрос по свойству пользовательского типа - PullRequest
0 голосов
/ 10 июля 2019

Я хочу использовать массив Postgres для хранения событий для каждого отправителя.Каждое событие сохраняется как пользовательский тип (объект) Postgres.

Как я могу запрашивать записи по свойствам пользовательского типа?Это возможно или нет?

Если да, могу ли я разместить индекс любого типа в столбце массива для ускорения запросов?

Создать пользовательский тип:

CREATE TYPE sender_event AS (
  event_timestamp TIMESTAMP(3),
  message TEXT
);

Создатьтаблица с массивом пользовательских типов:

CREATE TABLE sender_history (
    sender varchar(30),
    events  sender_event[]
);

Вставить несколько записей в таблицу:

INSERT INTO sender_history VALUES 
('sender1', ARRAY[(now(), 'Message text 1')::sender_event]),
('sender2', ARRAY[(now(), 'Message text 2')::sender_event])

Как найти все записи, в массиве которых содержится объект со свойством messageравно «Текст сообщения 2»?

Например, что-то вроде этого (это не работает):

SELECT * FROM sender_history
WHERE events.message = 'Message text 2'

Ожидаемый результат - вторая запись в этой таблице.

Ответы [ 2 ]

1 голос
/ 10 июля 2019

При поиске в массиве определенного элемента вам нужно расширить его до unnest() перед:

демо: дб <> скрипка

SELECT * 
FROM 
    sender_history, 
    unnest(events) as event
WHERE event.message = 'Message text 2'

Но, тем не менее, я бы действительно рекомендовал не использовать пользовательские типы в этом случае. Вместо этого, как сказал @a_horse_with_no_name, вам следует нормализовать структуру таблицы.

1 голос
/ 10 июля 2019

Вам нужно развернуть эти массивы, если вы хотите применить условие:

SELECT sh.*
FROM sender_history sh
WHERE exists (select *
              from unnest(sh.events) as x
              where x.message = 'Message text 2');

Но это лучше хранить в правильно нормированных отношениях один ко многим.

Цитата из руководства

Массивы не являются наборами; поиск определенных элементов массива может быть признаком неправильного проектирования базы данных. Попробуйте использовать отдельную таблицу со строкой для каждого элемента, который будет элементом массива. Это будет легче для поиска, и, вероятно, лучше масштабируется для большого количества элементов.

...