我使用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?它不斷提示「全文索引」,但我認爲這就是這樣。