使用 pg_search 和 GIN 索引大型文档

Indexing large documents with pg_search and GIN

我正在使用 Rails 3 为我自己和我的朋友们建立一个论坛(出于各种原因我没有使用开箱即用的论坛)而且我正处于我的地步'试图实现论坛的全文搜索。没有什么特别的——如果有人搜索字符串 "morning",我希望能够显示包含 "morning" 这个词的所有论坛主题的列表 post。我一直在使用 pg_search 进行搜索,但速度很慢(5 秒以上),因为我们已经有 300 个论坛线程和 200k+ posts,其中一些是 4k+ 个字符,仅在一个 post。所以我有这个 multisearch 迁移:

class CreatePgSearchDocuments < ActiveRecord::Migration
  def self.up
    say_with_time("Creating table for pg_search multisearch") do
      create_table :pg_search_documents do |t|
        t.text :content
        t.belongs_to :searchable, :polymorphic => true, :index => true
        t.timestamps null: false
      end
      add_index :pg_search_documents, :content, using: "gin"
      PgSearch::Multisearch.rebuild(Post)
      PgSearch::Multisearch.rebuild(Reply)
    end
  end
end

但是当我 运行 迁移时失败并出现此错误:

PG::ProgramLimitExceeded: ERROR:  index row size 3080 exceeds maximum 2712 for index "index_pg_search_documents_on_content"
HINT:  Values larger than 1/3 of a buffer page cannot be indexed.
Consider a function index of an MD5 hash of the value, or use full text indexing.

到目前为止,谷歌搜索得到了以下信息:

我实现的相关片段Post:

class Post < ActiveRecord::Base
  include PgSearch

  multisearchable against: [:subject, :sanitized_content]

  def sanitized_content
    ActionView::Base.full_sanitizer.sanitize(content).gsub(/[^\w ]/, ' ').squeeze(" ")
  end
end

(我也试过从 multisearchable-against 数组中删除 :subject ,以防它是一个未净化的主题导致问题;这让我在错误中下降到 row size 2800,但没有修复它。)

所以...我错过了什么? GIN 索引不应该能够处理大型文本文档吗?我是否需要像 this answer 那样先将我的文档转换为 tsvectors?它一直在提示 "full text indexing",但我认为就是这样。

为了以后的人谷歌:暂定使用

execute "CREATE INDEX idx_fts_search_content ON pg_search_documents USING gin(to_tsvector('english', content))

而不是

add_index :pg_search_documents, :content, using: "gin"

已修复。到目前为止,索引的作用不大,搜索所有内容需要 8.1 秒,但至少迁移现在可以运行!

编辑:错过了一件重要的事情。实际命令应该是:

execute "CREATE INDEX idx_fts_post_content ON posts USING gin(to_tsvector('english', coalesce(\"posts\".\"content\"::text, '')))"

如果您没有 coalesce(),它将不会使用索引。