我使用Rails 3为自己和我的朋友构建了一个论坛(由于各种原因,我没有使用一个开箱即用的论坛),而且我处于我正在尝试为论坛实施全文搜索。没有什么奇特的 - 只要有人搜索字符串“早上”,我希望能够显示所有论坛主题的列表,其中包含单词“morning”的帖子。我一直在使用pg_search进行搜索,但速度很慢(5秒以上),因为我们已经在300个论坛帖子中发布了200k +帖子,其中一些帖子只有4k +个字符。所以我有这个迁移multisearch:使用pg_search和GIN为大文档编制索引
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.
到目前为止,谷歌搜索已经得到了我如下:
对于处理100,000个以上的词位,GIN索引要优于GIST索引。这意味着,我认为GIN指标应该能够处理那些只有700字
我有一个猜想,这个错误是关于一个单个值而非文件的长度,以及担心职位这是由于我在论坛帖子中允许使用HTML标签的一个子集,所以不是存储post.content,而是存储post.sanitized_content。这将去除所有HTML,然后用空格替换标点符号,然后去除重复项,如下所示:
ActionView::Base.full_sanitizer.sanitize(content).gsub(/[^\w ]/, ' ').squeeze(" ")
。这得到了错误信息下降到index row size 2848 exceeds maximum 2712
,所以它显然做东西,但还不够。然后我理智地检查了pg_search实际上允许我使用这样的动态方法,而且它不仅仅是暗中失败。根据文档,“但是,如果你在以下情况下调用任何动态方法,将使用以下策略”,因此它们似乎处理得很好。
有关我实施后的碎片:
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-反序列主题,在情况下,它是一个unsanitized主题导致的问题;这让我下降到row size 2800
的错误,但没有解决它。)
所以...我错过了什么? GIN索引不能处理大型文本文档吗?我是否需要首先将文档转换为tsvectors,如this answer?它不断提示“全文索引”,但我认为这就是这样。