在 Rails 应用程序中,我正在尝试和修补在 postgres 中为现有数据添加 fts。这是我所做的:
class AddNameFtsIndexToCompanies < ActiveRecord::Migration
def up
execute(<<-'eosql'.strip)
DROP INDEX IF EXISTS index_companies_name;
CREATE INDEX index_companies_name
ON companies
USING gin( (to_tsvector('english', "companies"."name")) );
eosql
execute(<<-'eosql'.strip)
ALTER TABLE companies ADD COLUMN name_tsv tsvector;
CREATE TRIGGER tsv_name_update
BEFORE INSERT OR UPDATE ON companies FOR EACH ROW
EXECUTE PROCEDURE tsvector_update_trigger(name_tsv, 'pg_catalog.english', name);
CREATE INDEX index_companies_fts_name ON companies USING GIN (name_tsv);
eosql
end
def down
execute(<<-'eosql'.strip)
DROP INDEX IF EXISTS index_companies_name
eosql
execute(<<-'eosql'.strip)
DROP INDEX IF EXISTS index_fts_name;
DROP TRIGGER IF EXISTS tsv_name_update ON companies;
ALTER TABLE companies DROP COLUMN name_tsv
eosql
end
end
name_tsv 列的值仍为空。但是为了快速测试,我尝试了这个:
input_data = "foo"
Company.where(["to_tsvector(companies.name) @@ plainto_tsquery(?)", input_data ])
并将其与此进行比较:
input_data = "foo"
Company.where(["companies.name ilike ? ", "%#{input_data}%"])
而前者速度较慢。
问题:
1. 为什么速度较慢?
2. 为现有数据填充 tsvector 列的最佳做法是什么?
虽然我的问题与 Rails 应用程序有关,但通常更多的是关于 postgresql fts,所以仍然欢迎任何特定于 postgres 的解决方案。