在ef core中使用postgres資料庫的全文檢索功能實戰之中文支援

wjsgzcn發表於2020-05-15

前言

有關通用的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

再次執行查詢,發現已經能精確匹配到新詞彙。

 

相關文章