前言
有關通用的postgres數據庫全文檢索在ef core中的使用方法,參見我的上一篇文章。
本文實踐了zhparser中文插件進行全文檢索。
准備工作
安裝插件,最方便的方法是直接使用安裝好插件的docker鏡像,比如
docker pull chenxinaz/zhparser
該鏡像的postgres數據庫版本為10,如果你想要更新的版本,可以自行創建dockerfile進行build。
使用如下命令啟動你的容器,偵聽在5432端口。
docker run --name pgcn -p 5432:5432 -e POSTGRES_PASSWORD=123456 -d chenxinaz/zhparser
修改migration文件
找到上篇文章添加觸發器的代碼,在其之前加入代碼,注冊組件。
migrationBuilder.Sql(@"CREATE EXTENSION zhparser;"); migrationBuilder.Sql(@"CREATE TEXT SEARCH CONFIGURATION chinese_zh (PARSER = zhparser);"); migrationBuilder.Sql(@"ALTER TEXT SEARCH CONFIGURATION chinese_zh ADD MAPPING FOR n,v,a,i,e,l WITH simple;"); migrationBuilder.Sql( @"CREATE TRIGGER article_title_search_vector_update BEFORE INSERT OR UPDATE ON articles FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger(title_vector, 'public.chinese_zh', title);"); migrationBuilder.Sql( @"CREATE TRIGGER article_abst_search_vector_update BEFORE INSERT OR UPDATE ON articles FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger(abst_vector, 'public.chinese_zh', abst);");
注意觸發器使用的插件名稱前面的public。
修改完畢后,執行`dotnet ef database update`,創建數據庫。
修改查詢代碼
var query = "阿一土鱉"; var config = "chinese_zh"; var data = db.Articles .Where(p => p.TitleVector.Matches(EF.Functions.ToTsQuery(config, query)) || p.AbstVector.Matches(EF.Functions.ToTsQuery(config, query))) .OrderByDescending(p => p.TitleVector.Rank(EF.Functions.ToTsQuery(config, query)) * 2.0 + p.AbstVector.Rank(EF.Functions.ToTsQuery(config, query))) .Select(p => new Article { Title = p.Title, Abst = p.Abst, TitleHL = EF.Functions.ToTsQuery(config, query).GetResultHeadline(config, p.Title, ""), AbstHL = EF.Functions.ToTsQuery(config, query).GetResultHeadline(config, p.Abst, ""), });
注意所有的地方都要加config,聲明使用的parser類型;如果漏掉了一些config,可能導致查詢結果不准或者無法高亮等問題。
代碼不停的重復ToTsQuery,不知道是否有便捷的寫法?
查詢發現,能夠命中數據庫表中的“阿一土鱉”記錄,但是詞向量字段只有“土鱉”,其他都被當作停止詞過濾了,為了更精確的查詢,識別“阿一土鱉”這個詞語,需要引入自定義詞典。
自定義詞典
這里為了簡單,直接在容器內添加和修改文件,大家可以自行采用更高效率的方法更新字典和配置。
#進入容器: docker exec -it <容器名稱> /bin/bash #進入目錄: cd /usr/share/postgresql/10/tsearch_data #添加文件 touch chinese.txt #向文件添加一行自定義詞匯: echo "阿一土鱉 1 1 n" >> chinese.txt,后面的1 1 n,分別是TF/IDF/詞性。 #修改conf文件,引入自定義詞典: echo "zhparser.extra_dicts = 'chinese.txt'" >> /var/lib/postgresql/data/postgresql.conf #退出容器。 exit #重啟容器: docker restart <容器名稱>
重新索引數據
自定義詞典更新后,如果需要重建索引,只需要執行sql更新相關字段,就會觸發更新索引的操作,從而更新vectors字段。
update articles set title = title
再次執行查詢,發現已經能精確匹配到新詞匯。