Создать объединенный индекс для столбца JSONB в PostgreSQL - PullRequest
1 голос
/ 26 марта 2020

Мне нужно установить комбинированный индекс для двух полей из JSONB в моей PostgreSQL БД. Я могу установить индекс для одного поля, например, так (используя ActiveRecord в моем приложении на Rails 6):

add_index :my_table,
  "(content->'reference')",
  using: :gin,
  name: 'index_my_table_on_content_reference'

Это работает, как и ожидалось. Однако, когда я пытаюсь установить комбинированный индекс для двух полей, я получаю следующую ошибку:

add_index :my_table, 
  ["(content->'reference')", "(content->'ext_id')"], 
  using: :gin,
  name: 'index_my_table_on_content_ref_and_ext_id'
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column "(content->'reference')" does not exist

Что я делаю неправильно и как я могу создать комбинированный Индекс для нескольких полей в столбце JSONB?

И прежде чем вы спросите: Да, у каждого BLOB-объекта JSONB есть ключ с именем reference.

Использование: Ruby 2.6.5, Rails 6.0 PostgreSQL 11

Ответы [ 2 ]

0 голосов
/ 26 марта 2020

Ошибка PG::UndefinedColumn: ERROR: column "(content->'reference')" does not exist означает, что он обрабатывает "(content->'reference')" как имя столбца.

Воспроизведение с SQL:

create index my_table_json_idx on my_table using gin(
   (content->'reference'),
   "(content->'ext_id')"
);

Обратите внимание на кавычки вокруг второго выражения.

Кажется, есть проблема с вашей библиотекой ActiveRecord, и она экранирует ваше выражение jsonb, когда это нежелательно.

Либо используйте обычный SQL, либо попытайтесь заставить библиотеку ActiveRecord не покинуть вашу библиотеку. выражение.

После некоторого поиска в Google я думаю, что изменение массива на строку "(content->'reference'), (content->'ext_id')" может сработать.

0 голосов
/ 26 марта 2020

Ya Rails не знает, как создать дамп индекса jsonb, используя ruby. Так что SQL будет путь к go. Это была очень хорошая статья для меня, когда я начал возиться с jsonb Rails & jsonb

def change
  reversible do |dir|
    dir.up do 
      execute <<-SQL
       CREATE INDEX IF NOT EXISTS idx_my_table_on_content_references on my_table using gin ((content->>'reference'));
      SQL
    end

    dir.down {execute "DROP INDEX IF EXISTS idx_my_table_on_content_references;"}
  end
end
...