在我将要实现的仿照博客园搜索功能的简易网站中,需要用到Lucene.net进行查询,因此我整理了一下我收集的资料。
现实世界中包含两种类型的数据:结构化数据和非结构化数据
结构化数据很容易进行搜索,比如数据库包含的就是结构化数据,可以利用sql进行查询。但是对于非结构化数据,比如word、txt文件中包含的内容则属于非结构化数据。要对这些数据进行查找,只能采用顺序扫描的方式,但是顺序扫描的方式速度很慢。
但是在Lucene的世界中,把所有数据都作为字符串来处理,通过Lucene来进行查找,通常会分成两步,一步就是创建索引,另一步就是查找索引。
因为创建好的索引属于结构化数据,所以可以很快的进行查找。并且Lucene创建索引的方式采用的倒排索引的存储。
每个字符串都指向包含此字符串的文档(Document)链表,称谓倒排表。采用倒排表进行存储的索引结构就称为倒排索引。
也许有人会说,创建索引的时间会非常长,加上搜索索引的时间不一定会比直接采用顺序查找的速度要快。这个看法我是很赞同的,我就曾经采用Lucene创建索引,索引一篇word书籍,整整索引了八个小时才完成。我想如果我打开word直接查找也就是几分钟的事情。但是我为什么非要建立索引不可呢?原因也很简单,就是顺序扫描每次搜索都会重新执行一次,但是索引只需要索引一次,以后就都可以使用。这也就是创建索引的根本目的:一次索引,多次使用。
在搜索的过程中,我们往往是想让相关度较高的排在前面,这就会用到权重的概念。
找出词(Term)对文档重要性的过程称为计算词的权重(Weight)的过程。搜索出来的文档应该是按照权重的顺序进行排列,按从小到大的次序。
计算词的权重会关系到两个参数,一个是词(Term),另一个是文档(Document).
词的权重表示的是此词在此文档中的重要程度,越重要的词有越大的权重,因而在计算文档之间的相关性中将发挥更大的作用。
Lucene搜索过程通常分为三步:创建、索引、搜索
- 被索引的文档用Document对象表示
- IndexWriter通过函数adDocument将文档添加到索引中,实现创建索引的过程
- Lucene的索引采用的反向索引。对应我前面说的反向链表
- 当用户有请求时,Query代表用户的查询语句。
- IndexSearcher通过函数search搜索 Lucene Index
- IndexSearcher计算term weight和score并且将结果返回给用户。再返回给用户数据之前,Lucene还会按照权重进行排序
- 返回给用户的文档集合用TopDocsCollector表示
Lucene中的基本概念:Term (词) Document(文档) Field(字段(和数据库字段类似)) Query(查询) QueryParser(查询解析器) IndexWriter(负责生成索引并存储)
IndexReader(读取硬盘中的索引文件并存入内存) Hits(命中 我也不能很好的翻译这个词的意思 就是返回搜索的数据)
Lucene。net的基本使用方法
1 public void CreateIndex()//创建索引 2 { 3 Document doc = new Document(); 4 doc.Add(new Field("name", "我是郭志奇", Field.Store.YES, Field.Index.NOT_ANALYZED)); 5 doc.Add(new Field("val", "", Field.Store.YES, Field.Index.ANALYZED)); 6 IndexWriter writer = new IndexWriter(FSDirectory.Open(new DirectoryInfo("")), new Standard Analyzer(), true, IndexWriter.MaxFieldLength.LIMITED); 7 writer.AddDocument(doc); 8 writer.Optimize(); 9 writer.Close(); 10 } 11 12 13 public void Search(string queryString, int num)//搜索 14 { 15 IndexReader reader = IndexReader.Open("", true); 16 IndexSearcher searcher = new IndexSearcher(reader); 17 //创建查询 18 Analyzer analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29); 19 QueryParser parser = new QueryParser("", analyzer); 20 Query query = parser.Parse(queryString); 21 TopScoreDocCollector collector = TopScoreDocCollector.create(num, true); 22 Hits hits = searcher.Search(query); 23 //以后就可以对获取到的collector数据进行操作 24 for (int i = 0; i < hits.Length(); i++) 25 { 26 Document doc = hits.Doc(i); 27 Field keyFieldVal = doc.GetField("key"); 28 string strKey = keyFieldVal.StringValue();//获取到Field 键值key的值 29 } 30 } 31 public void DeleteIndex()//删除索引 32 { 33 34 IndexWriter writer = new IndexWriter(FSDirectory.Open(new DirectoryInfo("")), new Standard Analyzer(), true, IndexWriter.MaxFieldLength.LIMITED); 35 writer.DeleteAll();//删除所有的索引 36 writer.DeleteDocuments(new Term("key", "val"));//删除该词条 37 //注意 在执行这个删除操作的时候,其实lucene本身并没有将数据从硬盘删除,而是保存到了一个单独的后缀名为.del的文件中。 38 writer.Commit();//进行提交操作 标记为删除的索引会被从硬盘删除 39 40 }
Lucene可以进行的操作方法有很多,分词器也有很多,但是Lucene.net自带的分词器不能很好的支持中文,因此对于有中文的搜索我推荐盘古分词,很好很强大。
还有一点用惯.net的朋友使用Lucene.net的时候会觉得不习惯,因为在.net中是属性的东西,在Lucene.net中是用方法表示的,因为据我所知,在Java中是不存在和.net中的属性一说的。
索引:
Asp.net MVC 使用Autofac的简单使用 IOC (2012-12-12 13:16) | 8 | 649 | 547 | |||
Asp.net MVC 仿照博客园的简单网站首页 列表设计 (2012-12-11 22:21) | 发布 | 12 | 928 | 277 | ||
为什么要从Web form过渡到MVC中 (2012-12-09 22:43) | 发布 | 88 | 5253 | 478 | ||
Asp.net MVC3 企业网站系统高仿博客园 首页左侧列表页面 实现效果 (2012-12-08 19:11) | 发布 | 41 | 2506 | 361 | ||
Asp.net MVC 3 开发企业网站系统仿照博客园部分功能--总体设计 (2012-12-05 23:41) | 发布 | 36 | 2064 | 515 | ||
Asp.net MVC 3 开发简单的企业系统开篇--数据库 (2012-12-03 21:03) | 发布 | 43 | 3016 | 351 | ||
Asp.net MVC 3 开发一个简单的企业网站系统 (2012-12-02 21:09) |
我又回来了,回到了技术最前线,