• 在ef core中使用postgres数据库的全文检索功能实战之中文支持


    前言

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

    再次执行查询,发现已经能精确匹配到新词汇。

  • 相关阅读:
    navicat执行大容量的.sql文件时的设置
    unity3d的四元数 Quaternion
    Unity运行时刻资源管理
    unity3d 加密资源并缓存加载
    unity3d webplayer 16:9 居中显示模板
    quaternion*Vector3的新理解
    PoolManager
    网上关于碰撞的资料
    游戏美术:色彩原理
    unity3d下载Obb分包文件
  • 原文地址:https://www.cnblogs.com/wjsgzcn/p/12894401.html
Copyright © 2020-2023  润新知