Lucene.Net 站内搜索
一 全文检索:
like查询是全表扫描(为性能杀手)
Lucene.Net搜索引擎,开源,而sql搜索引擎是收费的
Lucene.Net只是一个全文检索开发包(只是帮我们存数据取数据,并没有界面,可以看作一个数据库,只能对文本信息进行检索)
Lucene.Net原理:把文本切词保存,然后根据词汇表的页来找到文章
二 分词算法:
//一元分词算法(引用Lucene.Net.dll)
一元分词算法
//二元分词算法(CJK:China Japan Korean 需要再引用CJKAnalyzer.cs/CJKTokenizer.cs)
二元分词算法
//基于词库的分词算法(盘古分词算法)
打开PanGu4Luene\WebDemo\Bin,将Dictionaries添加到项目根路径(改名Dict),对于其下的文件,在其属性里,输出目录修改为如果较新则复制
添加PanGu.dll的引用(如果直接引用PanGu.dll则必须不带PanGu.xml)
添加PanGu4Luene\Release中PanGu.Luene.Analyzer.dll的引用
其中PanGu_Release_V2.3.1.0\Release\DictManage.exe可以查看Dict.dct二进制词库,既可以查看词汇也可以加入词汇
盘古分词算法
三 写入索引
Luene.Net写入类介绍
打开文件夹,指定要写入的文件夹
文件加锁,避免两个人同时写入文件(并发)
判断是否文件中有数据,有的话就更新数据,没有就创建
逐一读取待读文件中文本并写入文档
写之后进行close,则表示解锁,可以由其他人写入(加锁写入过程中程序出现bug需要强制解锁时可能出问题)
各种类的作用:
Directory保存数据:FSDirectory(文件中),RAMDirectory(内存中)
IndexReader对索引库进行读取的类,IndexWriter对索引库进行写的类
IndexReader的bool IndexExists(Directory directory)判断目录是否是一个索引目录
IndexWriter的bool IsLocked(Directory directory)判断目录是否是锁定的
IndexWriter在进行写操作时会自动加锁,close的时候会自动解锁.IndexWriter.Unlock方法手动解锁(比如还没来得及close IndexWriter程序就崩溃了,可能造成一直被锁定)
IndexWriter(Directory dir,Analyzer a,bool create,MaxFieldLength mfl)写入哪个文件夹,采用什么分词算法,是否是创建,最大大小
void AddDocument(Document doc),向索引中添加文档
Add(Field field)向文档中添加字段
DeleteAll()删除所有文档,DeleteDocuments按照条件删除文档
File类得构造函数 Field(string name,string value,Field.Store store,Field.Index index,Field.TermVector termVector)
上面依次表示:(字段名,字段值,是否把原文保存到索引中,index表示如何创建索引(Field.Index需要进行全文检索,NOT_ANALYZED不需要的),termVector表示索引词之间的距离,超出则关联度低)
处理并发(写的时候只能逐一写入):用消息队列保证只有一个程序(线程)对索引操作,其他程序不直接进行索引库的写入,而是把要写入的数据放入消息队列,由单独的程序从消息队列中取数据进行索引库的写入
文章在新增和编辑时写入索引:
引用4个ServiceStack的dll用于队列
引用Quartz.dll/Common.Logging.dl用于定时任务
引用Lucene.Net.dll/PanGu.dll/PanGu.Lucene.Analyzer.dll用于写入索引
添加Dictionary改名Dict,旗下文件修改为如果较新则复制
文章新增或编辑时入队列
文章出队列写入索引
写入索引如果报错:
未能加载文件或程序集“PanGu, Version=2.3.0.0, Culture=neutral, PublicKeyToken=null”
或它的某一个依赖项。系统找不到指定的文件。
原因:
执行这个写入索引的令一个程序也需要引用PanGu.dll,最先执行写入索引的程序与后面真正类所在的索引是相互依赖的。
四 文章搜索:
query.Add(new Term("字段名","关键词"))
query.Add(new Term("字段名2","关键词2"))
类似于:where 字段名contains关键词 and 字段名2contains关键词2
PhraseQuery用于进行多个关键词的检索
PhraseQuery.SetSlop(int slop)用来设置单词之间的最大距离
BooleanQuery可以实现字段名contains关键词or字段名2contains关键词2
搜索时所采用的分词算法必须和生成索引时一致,即盘古分词算法
总条数 totalSize = collector.GetTotalHits()
查询结果集合应该是从(pagenum-1)*5,pagenum*5,但是collector.TopDocs(m,n)的m是从0开始、n是条数
NewsController.ashx?action=search
五 写入索引优化:
通过多线程避免界面卡死:
因为耗时操作会阻塞主进程,所以需要把耗时操作放入子线程
因为主线程关闭,则子线程也会关闭,所以需要把子线程设置为后台子线程,这样主线程关闭,子线程会继续
示例:
testThread.Form1.cs
实例:
//定时任务,子进程中出队列,然后写入文章索引,关闭窗口时终止子进程(出队列)和quartz.net进程
首先,启动窗体,执行定时任务,而定时的任务是进行新闻的出队列
然后,新闻的出队列是耗时操作,需要委托子进程,并设为后台进程,然后开始执行进程,其中出队列进程的控制由while(IsRunning)控制,先预先设置IsRunning=true
IsRunning = true;
Thread thread = new Thread(RunScan);//委托给子线程去RunScan
thread.IsBackground = true;//该子线程为后台线程
thread.Start();//执行该后台子线程,去执行RunScan方法
然后,执行出队列这个后台子进程
public static bool IsRunning { get; set; }//是否继续线程
public void RunScan()
{
while (IsRunning)//一旦窗体关闭,IsRunning=false,该进程终止
{...
然后,一直执行这个子进程,直到窗体被关闭,这时设置IsRunning=false使还在执行的这个后台子进程Thread的RunScan()终止,同时还需终止后台Quartz.net进程,避免窗体关闭而进程还在
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
NewsIndexer.IsRunning = false;//终止后台子进程RunScan方法
SendNewRegisterUM.schedWNI.Shutdown();//还需要终止后台Quartz.net进程,避免窗体已关闭,但是进程依然在
}
Timer.NewsIndex.cs
TimerForm.FormMain.cs
获取html的InnerText
搜索出来的不仅只是Title,还需要预览一部分内容body
用Lucene.net放入索引的时候需要过滤html标签
解决索引中body中全是html标签的问题,不利于搜索,很多垃圾信息,显示不方便。
使用HtmlAgilityPack进行innerText处理.
考虑文章编辑\重新索引等问题,需要先把旧的文档删除,再增加新的(等价于update)HTML解析器:输入一个html文档,提供对html文档操作的接口
开发包HtmlAgilityPack.1.4.0.zip,用于把html标签进行innerText后再放入索引库
引用 HtmlAgilityPack.dll
示例:
示例
实例:
实例
一键建立新闻索引:
入队列:
如果新闻太多,应该分批次进行入队列建立索引
NewsController.ashx
NewsBLL.cs
出队列:
每次出队列都进行一次索引路径的打开读取和关闭,效率低
全部出队列之前先打开索引目录,之后才关闭索引目录,最后才等待下一次client的队列中新数据
每次出队列加入检索索引之前,都需要删除文档索引中的相同id的文档索引,因为"编辑新闻"和"一键重建全文索引"都会再次加入同id的索引
六 搜索优化:
搜索结果高亮显示:
搜索结果中 获取最匹配的摘要段,关键词需要高亮显示
引用 PanGu.HighLight.dll
Front.FrontHelper.cs
Front.News.NewsController.ashx
七 扩展任务:
项目任务:完成新闻搜索、视频笔记搜索功能,而且是综合搜索
逻辑思路://搜索(分页\高亮显示)-->建立索引-->出队列-->入队列T_Segment(Id,Name,note,ChapterId)\T_News(Id,Title,NewsContent,CategoryId)
综合搜索:
入队列:
Admin/Course/CateogoryController.ashx?action=allSegmentIndex
BLL/CourseBLL.cs
出队列并写入索引 :
Timer/NewsAndSegmentIndex.cs
综合搜索:
Front/News/NewsController.ashx?action=search
Lucene.Net 站内搜索的更多相关文章
- Lucene.net站内搜索—6、站内搜索第二版
目录 Lucene.net站内搜索—1.SEO优化 Lucene.net站内搜索—2.Lucene.Net简介和分词Lucene.net站内搜索—3.最简单搜索引擎代码Lucene.net站内搜索—4 ...
- Lucene.net站内搜索—5、搜索引擎第一版实现
目录 Lucene.net站内搜索—1.SEO优化 Lucene.net站内搜索—2.Lucene.Net简介和分词Lucene.net站内搜索—3.最简单搜索引擎代码Lucene.net站内搜索—4 ...
- Lucene.net站内搜索—4、搜索引擎第一版技术储备(简单介绍Log4Net、生产者消费者模式)
目录 Lucene.net站内搜索—1.SEO优化 Lucene.net站内搜索—2.Lucene.Net简介和分词Lucene.net站内搜索—3.最简单搜索引擎代码Lucene.net站内搜索—4 ...
- Lucene.net站内搜索—3、最简单搜索引擎代码
目录 Lucene.net站内搜索—1.SEO优化 Lucene.net站内搜索—2.Lucene.Net简介和分词Lucene.net站内搜索—3.最简单搜索引擎代码Lucene.net站内搜索—4 ...
- Lucene.net站内搜索—2、Lucene.Net简介和分词
目录 Lucene.net站内搜索—1.SEO优化 Lucene.net站内搜索—2.Lucene.Net简介和分词Lucene.net站内搜索—3.最简单搜索引擎代码Lucene.net站内搜索—4 ...
- Lucene.net站内搜索—1、SEO优化
目录 Lucene.net站内搜索—1.SEO优化 Lucene.net站内搜索—2.Lucene.Net简介和分词Lucene.net站内搜索—3.最简单搜索引擎代码Lucene.net站内搜索—4 ...
- Lucene.net站内搜索-最简单搜索引擎代码
Lucene.Net核心类简介 先运行写好的索引的代码,再向下讲解各个类的作用,不用背代码. (*)Directory表示索引文件(Lucene.net用来保存用户扔过来的数据的地方)保存的地方,是抽 ...
- 站内搜索——Lucene +盘古分词
为了方便的学习站内搜索,下面我来演示一个MVC项目. 1.首先在项目中[添加引入]三个程序集和[Dict]文件夹,并新建一个[分词内容存放目录] Lucene.Net.dll.PanGu.dll.Pa ...
- 使用Lucene.NET实现简单的站内搜索
使用Lucene.NET实现简单的站内搜索 导入Lucene.NET 开发包 Lucene 是apache软件基金会一个开放源代码的全文检索引擎工具包,是一个全文检索引擎的架构,提供了完整的查询引擎和 ...
随机推荐
- 理解HMM
hidden markov model markov model: 把一个总随机过程看成一系列状态的不断转移, 其特性主要使用转移概率来表示. HMM:认为模型的状态是不可观测的(hidden), 能 ...
- sdut 2153 Clockwise (2010年山东省第一届ACM大学生程序设计竞赛)
题目大意: n个点,第i个点和第i+1个点可以构成向量,问最少删除多少个点可以让构成的向量顺时针旋转或者逆时针旋转. 分析: dp很好想,dp[j][i]表示以向量ji(第j个点到第i个点构成的向量) ...
- ZOJ 1113 u Calculate e
原题链接 题目大意:迭代求自然常数e. 解法:没什么好说的,注意数据类型和输出格式. 参考代码: #include<stdio.h> #include<math.h> int ...
- 关于JSP的C标签之forEach循环分隔符
页面中可能说出现在forEach循环中间需要出力分隔符的问题, 比如: 小明 1年级,小王 2年级, 小张 3年级(循环单位是 ${bean.name} ${bean.class}) 此时的逗号出力, ...
- U盘
U盘里的.Trashes是什么文件,要怎么去掉?为什么会出现这个文件? 这是苹果电脑的垃圾文件. 1.在苹果电脑上删除文件后,没有清空回收站,就会留下这些文件. 2.可以重新插入Mac, 然后会发现T ...
- android中的DatePicker与TimePicker
1.布局文件 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns ...
- input、select等表单元素的对齐问题
今天在写页面时,发现了一个问题,当INPUT.SELECT及用图片做的button放在一起(并排放一起)时,没法子对齐,自己以不愿再加其他代码.也不愿使用JS来实现图片button的效果,试好半天,发 ...
- 黑马程序员——JAVA基础之内部类,匿名内部类
------- android培训.java培训.期待与您交流! ---------- 内部类 将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类). 内部类访问特点: • 内部 ...
- ps调色技能
色相/饱和度: 色相->当你看到一种颜色,你会很快的辨别他为什么颜色,比如说红色,绿色,黄色.选中某种颜色然后调整色相. 饱和度->色彩艳丽程度. 明度->调整图片暗亮 曲线:暗亮调 ...
- javascript jquery 常用方法
javascript splice() //删除数组成员 pop() //删除数组成员 jquery $.type(aaa) //判断对象类型