业务要求是对商品标题可以进行模糊搜索

例如用户输入了【我想查询下雅思托福考试】,这里我们需要先将这句话分词成【查询】【雅思】【托福】【考试】,然后搜索包含相关词汇的商品。

思路如下

首先我们需要把数据库里的所有商品内容,自动同步到 Lucene 的分词索引目录下缓存,效果如下

这里就用到了之前写的自动作业 Hangfire 大家可以参考下面的博文

https://www.cnblogs.com/jhli/p/10027074.html

定时更新缓存,后面就可以分词搜索了,更新索引代码如下

        public void UpdateMerchIndex()
{
try
{
Console.WriteLine($"[{DateTime.Now}] UpdateMerchIndex job begin..."); var indexDir = Path.Combine(System.IO.Directory.GetCurrentDirectory(), "temp", "lucene", "merchs");
if (System.IO.Directory.Exists(indexDir) == false)
{
System.IO.Directory.CreateDirectory(indexDir);
} var VERSION = Lucene.Net.Util.LuceneVersion.LUCENE_48;
var director = FSDirectory.Open(new DirectoryInfo(indexDir));
var analyzer = new JieBaAnalyzer(TokenizerMode.Search);
var indexWriterConfig = new IndexWriterConfig(VERSION, analyzer); using (var indexWriter = new IndexWriter(director, indexWriterConfig))
{
if (File.Exists(Path.Combine(indexDir, "segments.gen")) == true)
{
indexWriter.DeleteAll();
} var query = _merchService.Where(t => t.IsDel == false); var index = ;
var size = ; var count = query.Count(); if (count > )
{
while (true)
{
var rs = query.OrderBy(t => t.CreateTime)
.Skip((index - ) * size)
.Take(size).ToList(); if (rs.Count == )
{
break;
} var addDocs = new List<Document>(); foreach (var item in rs)
{
var merchid = item.IdentityId.ToLowerString(); var doc = new Document();
var field1 = new StringField("merchid", merchid, Field.Store.YES);
var field2 = new TextField("name", item.Name?.ToLower(), Field.Store.YES);
doc.Add(field1);
doc.Add(field2);
addDocs.Add(doc);// 添加文本到索引中 } if (addDocs.Count > )
{
indexWriter.AddDocuments(addDocs);
} index = index + ;
} } } Console.WriteLine($"[{DateTime.Now}] UpdateMerchIndex job end!");
}
catch (Exception ex)
{
Console.WriteLine($"UpdateMerchIndex ex={ex}");
}
}

剩下的就是去查询索引内容,匹配到id,然后去数据库查询响应id的项。

搜索代码

        protected List<Guid> SearchMerchs(string key)
{
if (string.IsNullOrEmpty(key))
{
return null;
}
key = key.Trim().ToLower(); var rs = new List<Guid>(); try
{
var indexDir = Path.Combine(System.IO.Directory.GetCurrentDirectory(), "temp", "lucene", "merchs"); var VERSION = Lucene.Net.Util.LuceneVersion.LUCENE_48; if (System.IO.Directory.Exists(indexDir) == true)
{
var reader = DirectoryReader.Open(FSDirectory.Open(new DirectoryInfo(indexDir)));
var search = new IndexSearcher(reader); var directory = FSDirectory.Open(new DirectoryInfo(indexDir), NoLockFactory.GetNoLockFactory());
var reader2 = IndexReader.Open(directory);
var searcher = new IndexSearcher(reader2); var parser = new QueryParser(VERSION, "name", new JieBaAnalyzer(TokenizerMode.Search));
var booleanQuery = new BooleanQuery(); var list = CutKeyWord(key);
foreach (var word in list)
{
var query1 = new TermQuery(new Term("name", word));
booleanQuery.Add(query1, Occur.SHOULD);
} var collector = TopScoreDocCollector.Create(, true);
searcher.Search(booleanQuery, null, collector);
var docs = collector.GetTopDocs(, collector.TotalHits).ScoreDocs; foreach (var d in docs)
{
var num = d.Doc;
var document = search.Doc(num);// 拿到指定的文档 var merchid = document.Get("merchid");
var name = document.Get("name"); if (Guid.TryParse(merchid, out Guid mid) == true)
{
rs.Add(mid);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"SearchMerchs ex={ex}");
} return rs;
}

对用户输入的话进行拆分分词代码 JiebaNet

        protected List<string> CutKeyWord(string key)
{
var rs = new List<string>();
var segmenter = new JiebaSegmenter();
var list = segmenter.Cut(key);
if (list != null && list.Count() > )
{
foreach (var item in list)
{
if (string.IsNullOrEmpty(item) || item.Length <= )
{
continue;
} rs.Add(item);
}
}
return rs;
}

需要添加的 nuget 引用的包和对应版本

Hangfire 1.7.0-beta1

Lucene.Net 4.8.0-beta00005

Lucene.Net.Analysis.Common 4.8.0-beta00005

Lucene.Net.QueryParser 4.8.0-beta00005

需要单独引用的dll文件

JiebaNet.Segmenter.dll 

下载地址

https://pan.baidu.com/s/1D7mQnow0FmoqedNYzugfKw

如果本地调试没有问题,发布到服务器上 自动执行作业就遇到这个问题

https://stackoverflow.com/questions/47746582/hangfire-job-throws-system-typeloadexception

 
System.TypeLoadException

Could not load type ‘***’ from assembly ‘***, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’.

其实这个报错并不是原因,把异常打印出来就知道了

原因是没有将 Resources 文件夹下的字典文件 dict.txt 发布到服务器上

这个坑让我浪费了半天时间。。。

【netcore基础】.Net core通过 Lucene.Net 和 jieba.NET 处理分词搜索功能的更多相关文章

  1. 【netcore基础】CentOS 7.6.1810 搭建.net core 2.1 linux 运行环境 nginx反向代理 supervisor配置自启动

    之前写过一篇Ubuntu的环境搭建博客,感觉一些配置大同小异,这里重点记录下 nginx 作为静态 angular 项目文件服务器的配置 参考链接 [netcore基础]ubuntu 16.04 搭建 ...

  2. Python3 与 C# 面向对象之~继承与多态 Python3 与 C# 面向对象之~封装 Python3 与 NetCore 基础语法对比(Function专栏) [C#]C#时间日期操作 [C#]C#中字符串的操作 [ASP.NET]NTKO插件使用常见问题 我对C#的认知。

    Python3 与 C# 面向对象之-继承与多态   文章汇总:https://www.cnblogs.com/dotnetcrazy/p/9160514.html 目录: 2.继承 ¶ 2.1.单继 ...

  3. .netCore+Vue 搭建的简捷开发框架 (4)--NetCore 基础 -2

    上节中,我们初步的介绍了一下NetCore的一些基础知识,为了控制篇幅(其实也是因为偷懒),我将NetCore 基础分为两部分来写. 0.WebAPI 项目的建立 1..NetCore 项目执行(加载 ...

  4. 动画基础--基于Core Animation(3)

    参考:https://zsisme.gitbooks.io/ios-/content/ 前面的文章动画基础--基于Core Animation(1),动画基础--基于Core Animation(2) ...

  5. 动画基础--基于Core Animation(2)

    参考:https://zsisme.gitbooks.io/ios-/content/ 前面的文章动画基础--基于Core Animation(1)提到了图层的基本概念以及可动画参数几何学等知识. 本 ...

  6. 动画基础--基于Core Animation(1)

    1.简介 上一篇文章[New learn]动画-基于UIView了解到了一些直接由UIView这个在UIKIT提供的类中提供的一些动画方法. 使用UIView的动画特性已经能够满足我们很多的需求,它是 ...

  7. Net Core使用Lucene.Net和盘古分词器 实现全文检索

    Lucene.net Lucene.net是Lucene的.net移植版本,是一个开源的全文检索引擎开发包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎, ...

  8. Lucene.net(4.8.0) 学习问题记录五: JIEba分词和Lucene的结合,以及对分词器的思考

    前言:目前自己在做使用Lucene.net和PanGu分词实现全文检索的工作,不过自己是把别人做好的项目进行迁移.因为项目整体要迁移到ASP.NET Core 2.0版本,而Lucene使用的版本是3 ...

  9. 【lucene系列学习四】使用IKAnalyzer分词器实现敏感词和停用词过滤

    Lucene自带的中文分词器SmartChineseAnalyzer不太好扩展,于是我用了IKAnalyzer来进行敏感词和停用词的过滤. 首先,下载IKAnalyzer,我下载了 然后,由于IKAn ...

随机推荐

  1. Oracle CPU使用率过高问题处理

    1.下载Process Explorer 2.打开Process Explorer,查看CPU使用情况最高的进程 3.双击该进程,查看详情 \ 4.    获取cpu使用最好的线程tid 5.     ...

  2. 策略梯度训练cartpole小游戏

    我原来已经安装了anaconda,在此基础上进入cmd进行pip install tensorflow和pip install gym就可以了. 在win10的pycharm做的. policy_gr ...

  3. wordpress引入文件

    引入顶部 <?php get_header(); ?> 引入侧栏 <?php get_sidebar(); ?> 引入底部 <?php get_footer(); ?&g ...

  4. android平台修改默认语言的那点事

    转自:https://blog.csdn.net/qinghua0706/article/details/8243858 最近开始做智能机,用的是展讯6820平台,第一个需求就是改默认语言,一般碰到不 ...

  5. 使用AShot进行网页全页截图

    import org.junit.Test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.Chrom ...

  6. hive sql 常见异常

    1.union Logging initialized using configuration in file:/home/xiaoju/hadoop/apache-hive-1.2.1-bin/co ...

  7. Android Chromium WebView学习启动篇

    Android从4.4起提供基于Chromium实现的WebView.此前WebView基于WebKit实现.WebKit提供网页解析.布局和绘制以及JS执行等基础功能.Chromium在WebKit ...

  8. 关于snowflake算法生成的ID转换为JS的数字类型由于过大导致JS精度丢失的问题

    JS的数字类型目前支持的最大值为:9007199254740992,一旦数字超过这个值,JS将会丢失精度,导致前后端的值出现不一致. JAVA的Long类型的       最大值为:922337203 ...

  9. EntityFramework.Extended 对EF进行扩展

    前言 Entity Framework 延伸系列目录 今天我们来讲讲EntityFramework.Extended 首先科普一下这个EntityFramework.Extended是什么,如下: 这 ...

  10. Hadoop集群datanode磁盘不均衡的解决方案【转】

    一.引言: Hadoop的HDFS集群非常容易出现机器与机器之间磁盘利用率不平衡的情况,比如集群中添加新的数据节点,节点与节点之间磁盘大小不一样等等.当hdfs出现不平衡状况的时候,将引发很多问题,比 ...