Сопоставление с образцом по ключу / значению jsonb
Я использую PostgreSQL 9.4. Мой стол имеет jsonb
колонка:
CREATE TABLE "PreStage".transaction (
transaction_id serial NOT NULL,
transaction jsonb
CONSTRAINT pk_transaction PRIMARY KEY (transaction_id)
);
CREATE INDEX idxgin ON "PreStage".transaction USING gin (transaction);
Я храню транзакции в терминах ключ / значение в столбце JSONB. Одним из требований является поиск имени клиента по значению ключа, поэтому я выполняю такой запрос:
SELECT transaction as data FROM "PreStage".transaction
WHERE transaction->>('HCP_FST_NM') ilike ('%neer%');
То, что я делаю, кажется, что запросу не нравится индекс GIN. Как сделать так, чтобы запрос использовал индекс GIN с поиском по шаблону без учета регистра?
Я пытался изменить jsonb
столбец к тексту, индексация его с помощью gin_trgm_ops
затем поиск необходимого текста, а затем преобразование результата в json
и затем поиск нужного ключа / значения. Этот подход, похоже, не работает.
1 ответ
Класс оператора индекса GIN по умолчанию jsonb_ops
не допускает сопоставления полнотекстового шаблона со значением. Подробности:
Лучшая стратегия индексации зависит от вашей полной ситуации. Есть много вариантов. Чтобы просто охватить один ключ, который вы представили, вы можете использовать функциональный индекс триграммы. Ты уже проверял gin_trgm_ops
Итак, вы уже знакомы с дополнительным модулем pg_trgm. Для тех, кто не:
После установки модуля:
CREATE INDEX idxgin ON "PreStage".transaction
USING gin ((transaction->>'HCP_FST_NM') gin_trgm_ops);
Тогда этот запрос поддерживается:
SELECT transaction AS data
FROM "PreStage".transaction
WHERE transaction->>'HCP_FST_NM' ILIKE '%neer%';
Я также удалил некоторые ненужные скобки.
В зависимости от неизвестных деталей, существуют различные варианты оптимизации охвата индекса.
Например, если во многих строках вообще отсутствует ключ 'HCP_FST_NM', сделайте это частичным индексом, чтобы исключить ненужные строки и сохранить индекс маленьким:
CREATE INDEX idxgin ON "PreStage".transaction
USING gin ((transaction->>'HCP_FST_NM') gin_trgm_ops)
WHERE transaction ? 'HCP_FST_NM';
?
бытьjsonb
оператор локализации.
И добавьте один и тот же предикат к каждому запросу, который должен использовать этот индекс:
SELECT transaction AS data
FROM "PreStage".transaction
WHERE transaction->>'HCP_FST_NM' ILIKE '%neer%'
AND transaction ? 'HCP_FST_NM'; -- even if that seems redundant.