2015-04-29 3 views
5

Ссылаясь на original stackoverflow question, я пытаюсь применить индексы gin к ключам в объектах массива в Postgres 9.4, но я не получаю результаты, как указано в первом ответе.Использование индексов в массиве json в PostgreSQL

Не могли бы вы исправить ошибку?

Следующие шаги были написаны ниже.

Часть 1: Создание таблицы и индексы

CREATE TABLE tracks (id serial, artists jsonb); 
CREATE INDEX tracks_artists_gin_idx ON tracks USING gin (artists); 
INSERT INTO tracks (id, artists) VALUES (1, '[{"name": "blink-182"}]'); 
INSERT INTO tracks (id, artists) VALUES (2, '[{"name": "The Dirty Heads"}, {"name": "Louis Richards"}]'); 

Часть 2: Запрос

SELECT * FROM tracks WHERE artists @> '{"name": "The Dirty Heads"}'; 
id | artists 
----+--------- 
(0 rows) 

Этот запрос дает пустые результаты.
Я также пытался использовать jsonb_path_ops индексы GIN.

Альтернативный индекс и запросы:

DROP INDEX tracks_artists_gin_idx; 
CREATE INDEX tracks_artistnames_gin_idx ON tracks USING gin (artists jsonb_path_ops); 
SELECT * FROM tracks WHERE artists @> '{"name": "The Dirty Heads"}'; 
id | artists 
----+--------- 
(0 rows) 
+1

В ответе в примере, на который вы ссылаетесь, в моем ответе отсутствовал массив. Это исправлено. @ Ответ на картофелят дает объяснение. –

+0

Для будущих зрителей на этот вопрос я нашел эту ссылку http://stackoverflow.com/a/30592076/2405689, в которой показано, как запросить массив 'jsonb' объектов, что-то вроде того, что должен выполнить вышеуказанный запрос. – ArchNoob

ответ

7

Этот конкретный jsonb пример из original answer отсутствовал слой массива [] вокруг непримитивного объекта для запроса локализации. С тех пор оно было исправлено.

поведение документированы для PostgreSQL 9.4.x jsonb Containment and Existence состояний:

Общий принцип заключается в том, что содержащийся объект должен соответствовать объект, содержащий в качестве структуры и содержания данных

...

Как специальное исключение из общего принципа, что структуры должны совпадать, массив может содержать элементарное значение

Специальное исключение позволяет сделать следующее:

CREATE TABLE tracks (id serial, artistnames jsonb); 
CREATE INDEX tracks_artistnames_gin_idx ON tracks USING gin (artistnames); 
INSERT INTO tracks (id, artists) VALUES (1, '["blink-182"]'); 
INSERT INTO tracks (id, artists) VALUES (2, '["The Dirty Heads", "Louis Richards"]'); 

Мы можем запрос на локализацию с использованием общего принципа:

SELECT * FROM tracks WHERE artistnames @> '["The Dirty Heads"]'; 
id |    artistnames    
----+--------------------------------------- 
    2 | ["The Dirty Heads", "Louis Richards"] 
(1 row) 

Мы также можем запросить сдерживание, используя специальное исключение, так как массив содержит примитивные типы:

SELECT * FROM tracks WHERE artistnames @> '"The Dirty Heads"'; 
id |    artistnames    
----+--------------------------------------- 
    2 | ["The Dirty Heads", "Louis Richards"] 
(1 row) 

Есть 4 примитивных типов, которые позволяют сдерживающее существование запросов на массивы для работы:

  1. строки
  2. номер
  3. булева
  4. null

Так как пример вы упомянули в вашем вопросе имеет дело с объектами вложенными внутри массива, мы не претендовать на особое исключение упомянутого выше:

CREATE TABLE tracks (id serial, artists jsonb); 
CREATE INDEX tracks_artists_gin_idx ON tracks USING gin (artists); 
INSERT INTO tracks (id, artists) VALUES (1, '[{"name": "blink-182"}]'); 
INSERT INTO tracks (id, artists) VALUES (2, '[{"name": "The Dirty Heads"}, {"name": "Louis Richards"}]'); 

Мы можем запросить для сдерживания, используя общий принцип:

SELECT * FROM tracks WHERE artists @> '[{"name": "The Dirty Heads"}]'; 
id |       artists       
----+----------------------------------------------------------- 
    2 | [{"name": "The Dirty Heads"}, {"name": "Louis Richards"}] 
(1 row) 

объекты не считаются примитивным типом, так что следующий запрос для сдерживания не претендовать на особое исключение, и поэтому не работает:

SELECT * FROM tracks WHERE artists @> '{"name": "The Dirty Heads"}'; 
id | artists 
----+--------- 
(0 rows) 
+0

@ErwinBrandstetter Моя первоначальная формулировка была неправильной для описания фактической проблемы и непреднамеренного унижения к вашему ответу (не понимал, что пока я не увидел, что я процитировал). Я изменил его, чтобы лучше отразить то, что на самом деле произошло. – potatosalad

+0

Мы живем, учимся. Очень хороший ответ. :) –

+0

Спасибо @ErwinBrandstetter и potatosalad – user2512324

Смежные вопросы