【问题标题】:Create combined index for JSONB column in PostgreSQL在 PostgreSQL 中为 JSONB 列创建组合索引
【发布时间】:2020-03-26 09:26:12
【问题描述】:

我需要在我的 PostgreSQL 数据库中的 JSONB 中的两个字段上设置组合索引。我可以像这样为单个字段设置索引(在我的 Rails 6 应用程序中使用 ActiveRecord):

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 列中的多个字段创建组合索引?

在你问之前:是的,每个 JSONB blob 都有一个名为 reference 的键。

使用:Ruby 2.6.5、Rails 6.0、PostgreSQL 11

【问题讨论】:

  • 当整个表达式被转义并被视为列名时,PG 会给出此错误。 create index my_table_json_idx on my_table using gin((content->'reference'), "(content->'ext_id')");。似乎 ActiveRecord 在不可取的情况下转义存在问题。
  • @Jindra 感谢您的反馈。所以你的建议是用纯 SQL 编写迁移?
  • 我不知道 Ruby On Rails 或您的 ActiveRecord 库,所以我无法真正帮助您。也许有办法告诉它不要逃跑。如果没有那么简单的 SQL。
  • @Jindra 我最终使用了纯 SQL。如果您愿意,请将您的建议作为答案发布。

标签: ruby-on-rails postgresql activerecord indexing jsonb


【解决方案1】:

错误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 库不逃避你的表达。

经过一些谷歌搜索后,我认为将数组更改为字符串 "(content->'reference'), (content->'ext_id')" 可能会起作用。

【讨论】:

    【解决方案2】:

    Ya Rails 不知道如何使用 ruby​​ 转储 jsonb 索引。所以SQL将是要走的路。当我开始搞乱 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
    

    【讨论】:

    • 这不会创建一个组合索引,但我仍然看到你在做什么。谢谢。
    • 您可以像使用常规列一样创建聚集索引。 ((content-&gt;&gt;'reference'), (content-&gt;&gt;'ext_id'))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-08
    • 1970-01-01
    • 2017-09-11
    • 1970-01-01
    • 1970-01-01
    • 2020-06-10
    相关资源
    最近更新 更多