现在的位置: 首页 > 综合 > 正文

lucene.net的一些基本使用方法和概念

2017年12月07日 ⁄ 综合 ⁄ 共 6832字 ⁄ 字号 评论关闭

lucene.net的一些基本使用方法和概念

Luceneapache(阿帕奇)组织的一个用java实现全文搜索引擎的开源项目。其功能非常的强大,但APIApplication Programming Interface应用程序编程接口),其实很简单的,它最主要就是做两件事:建立索引(IndexWriter)和进行搜索(IndexRead)。

1. 建立索引时最重要的几个术语

* Document:一个要进行索引的单元,相当于数据库的一行纪录,任何想要被索引的数据,都必须转化为Document对象存放。

* FieldDocument中的一个字段,相当于数据库中的Column (列),Fieldlucene比较多概念一个术语。

* IndexWriter:负责将Document写入索引文件(Document)中。通常情况下,IndexWriter的构造函数包括了以下3个参数:索引存放的路径(PathURL)分析器(Analyzer)和是否重新创建索引(BOOL)。特别注意的一点,当IndexWriter执行完addDocument方法后,一定要记得调用自身的close方法来关闭它。只有在调用了close方法后,索引器才会将存放在内在中的所有内容写入磁盘并关闭输出流。

* Analyzer:分析器,主要用于文本分词。常用的有StandardAnalyzer分析器,StopAnalyzer分析器,WhitespaceAnalyzer分析器等。

* Directory:索引存放的位置。lucene提供了两种索引存放的位置,一种是磁盘,一种是内存。一般情况将索引放在磁盘上;相应地lucene提供了FSDirectory(磁盘)和RAMDirectory(内存)两个类。

* Segment或者分割:SegmentLucene索引文件的最基本的一个单位。Lucene说到底就是不断加入新的Segment,然后按一定的规则算法合并不同的Segment以合成新的Segment

lucene建立索引的过程就是将待索引的对象转化为LuceneDocument对象,使用IndexWriter将其写入lucene 自定义格式的索引文件中。 

待索引的对象可以来自文件、数据库等任意途径,用户自行编码遍历目录读取文件或者查询数据库表取得ResultSet结果集),LuceneAPI只负责和字符串打交道。

1.1 Field 的解释

从源代码中,可以看出Field 构造函数如下:

Field(String  name, byte[] value, Field.Store store)

Field(String  name, Reader reader)

Field(String  name, Reader reader, Field.TermVector termVector)

Field(String  name, String value, Field.Store store, Field.Index index)

Field(String name, String value, Field.Store store, Field.Index index, Field.TermVector termVector)

Field当中有三个内部类:Field.Index,Field.Store,Field.termVector。其中

Field第一个参数(name)代表的是Document中一个列(字段)的名称,任意名称

Field第二个参数(value)代表的是对应Document中一个列(字段)要索引的表中的某个字段的信息。

* Field.Index有四个属性分别是:

Field.Index.TOKENIZED:分词索引

Field.Index.UN_TOKENIZED不分词进行索引,如作者名,日期等,Rod Johnson本身为一单词,不再需要分词。

Field.Index.NO:不进行索引,存放不能(不需要)被搜索的内容如文档的一些附加属性如文档类型, URL等。

Field.Index.NO_NORMS不分词,建索引.但是Field的值不像通常那样被保存,而是只取一个byte,这样节约存储空间。

* Field.Store也有三个属性分别是:

Field.Store.YES:索引文件本来只存储索引数据此设计将原文内容直接也存储在索引文件中,如文档的标题。

Field.Store.NO:原文不存储在索引文件中,搜索结果命中后,再根据其他附加属性如文件的Path,数据库的主键等,重新连接打开原文,适合原文内容较大的情况。

Field.Store.COMPRESS 压缩存储;

* termVectorLucene 1.4.3新增的它提供一种向量机制来进行模糊查询,很少用。

上面所说的Field属性与lucene1.4.3版本的有比较大的不同,在旧版的1.4.3lucene是通过Field.Keyword (...),FieldUnIndexed(...),FieldUnstored(...)Field.Text(...)来设置不同字段的类型以达 到不同的用途,而当前版本由Field.IndexField.Store两个字段的不同组合来达到上述效果。

还有一点说明,其中的两个构造函数其默认的值为Field.Store.NOField.Index.TOKENIZED。:

Field(String name, Reader reader)

Field(String name, Reader reader, Field.TermVector termVector)

限制Field的长度:

IndexWriter类提供了一个setMaxFieldLength的方法来对Field的长度进行限制,看一下源代码就知道其默认值为10000; 我们可以在使用时重新设置此参数。如果使用默认值,那么Lucene就仅仅对文档的前面的10000term进行索引,超过这一个数的文档就不会被建立 索引。

1.2 索引的合并、删除、优化

* IndexWriter中的addIndexes方法将索引进行合并;当在不同的地方创建了索引后,如果需要将索引合并,这时候使用addIndexes方法就显得很有意义。

可以通过IndexReader类从索引中进行文档的删除。IndexReader是很特别的一个类,看源代码就知道它主要是通过自身的静态方法来完成构造的。示例:

IndexReader reader = IndexReader.open("C:\\springside");

reader.deleteDocument(X); //这里的X是一个int的常数;不推荐这一种删除方法

reader.deleteDocument(new Term("name","springside"));//这是另一种删除索引的方法,按字段来删除,推荐使用这一种做法

reader.close();

优化索引:可以使用IndexWriter类的optimize方法来进行优先,它会将多个Segment进行合并,组成一个新的Segment,可以加 快建立索引后搜索的速度。另外需要注意的一点,optimize方法会降低建立索引的速度,而且要求的磁盘空间会增加。

2. 进行搜索时最常用的几个术语

* IndexSearcher:lucene中最基本的检索工具,所有的检索都会用到IndexSearcher工具。初始化IndexSearcher需要设置索引存放的路径,让查询器能定位索引而进行搜索。

* Query:查询,lucene中支持模糊查询,语义查询,短语查询,组合查询等等,如有TermQuery,BooleanQuery,RangeQuery,WildcardQuery等一些类。

* QueryParser: 是一个解析用户输入的工具,可以通过扫描用户输入的字符串,生成Query对象。

* Hits:在搜索完成之后,需要把搜索结果返回并显示给用户,只有这样才算是完成搜索的目的。在lucene中,搜索的结果的集合是用Hits类的实例来表示的。Hits对象中主要方法有:

length(): 返回搜索结果的总数,下面简单的用法中有用到Hit的这一个方法

doc(int n): 返回第n个文档

iterator(): 返回一个迭代器

这里再提一下Hits,这也是Lucene比较精彩的地方,熟悉hibernate的朋友都知道hibernate有一个延迟加载的属性,同样, Lucene也有。Hits对象也是采用延迟加载的方式返回结果的,当要访问某个文档时,Hits对象就在内部对Lucene的索引又进行一次检索,最后 才将结果返回到页面显示。

自己总结Lucene:Lucene是全文搜索。不会针对表中具体某一行而创建单独的索引。

1.搜集关键字keyword

2.创建索引 IndexWriter

3.进行索引IndexRead

Lucene.NET

可以给 Document 和 Field 增加权重(Boost),使其在搜索结果排名更加靠前。缺省情况下,搜索结果以 Document.Score 作为排序依据,该数值越大排名越靠前。Boost 缺省值为 1

Score = Score * Boost

通过上面的公式,我们就可以设置不同的权重来影响排名。

如下面的例子中根据 VIP 级别设定不同的权重。

Document document = new Document();
switch (vip)
{
  case VIP.Gold: document.SetBoost(2F); break;
  case VIP.Argentine: document.SetBoost(1.5F); break;
}

只要 Boost 足够大,那么就可以让某个命中结果永远排第一位,这就是百度等网站的"收费排名"业务。

Lucene.NET

Refurbishtime职位刷新时间

Sort sort = new Sort(new SortField("refurbishtime"SortField.AUTO,true));//特注:true降幂排序false升幂排序

             public const int SCORE = 0 ;  //相关度

                public const int DOC = 1 ;    //文挡号

                public const int AUTO = 2 ;   //自动识别

                public const int STRING = 3 ; //字符型

                public const int INT = 4 ;    //int

                public const int FLOAT = 5 ;  //float

                public const int CUSTOM = 9 ; //自定义

Lucene.NET关键字高亮

--------luceneSOSO.rar

Lucene.NET添加索引

--------luceneSOSO.rar

Lucene.NET更新索引

--------luceneSOSO.rar

Lucene.NET删除索引

--------luceneSOSO.rar

Lucene.NET

如何搜索

lucene的搜索相当强大,它提供了很多辅助查询类,每个类都继承自Query类,各自完成一种特殊的查询,你可以像搭积木一样将它们任意组合使用,完成一些复杂操作;另外lucene还提供了Sort类对结果进行排序,提供了Filter类对查询条件进行限制。你或许会不自觉地拿它跟SQL语句进行比较:lucene能执行andororder bywherelike %xx%操作吗?回答是:当然没问题!

7.1 各种各样的Query

下面我们看看lucene到底允许我们进行哪些查询操作:

7.1.1 TermQuery

首先介绍最基本的查询,如果你想执行一个这样的查询:content域中包含lucenedocument,那么你可以用TermQuery

Term t = new Term("content", " lucene");

Query query = new TermQuery(t);

7.1.2 BooleanQuery(布尔搜索)  其中的MUSTSHOULDMUST_NOT表示与、或、非,从字面意思很容易理解

如果你想这么查询:content域中包含javaperldocument,那么你可以建立两个TermQuery并把它们用BooleanQuery连接起来:
TermQuery termQuery1 = new TermQuery(new Term("content", "java");   
TermQuery termQuery 2 = new TermQuery(new Term("content", "perl");   
BooleanQuery booleanQuery = new BooleanQuery();  
booleanQuery.add(termQuery 1, BooleanClause.Occur.SHOULD);  
booleanQuery.add(termQuery 2, BooleanClause.Occur.SHOULD); 

或者
TermQuery termQuery1 = new TermQuery(new Term("content", "java");
TermQuery termQuery 2 = new TermQuery(new Term("content", "perl");
BooleanQuery booleanQuery = new BooleanQuery();
booleanQuery.add(termQuery 1, BooleanClause.Occur.SHOULD);
booleanQuery.add(termQuery 2, BooleanClause.Occur.SHOULD);

7.1.3 WildcardQuery通配符搜索

如果你想对某单词进行通配符查询,你可以用WildcardQuery,通配符包括?匹配一个任意字符和*匹配零个或多个任意字符,例如你搜索use*,你可能找到useful或者useless

Query query = new WildcardQuery(new Term("content", "use*");

7.1.4 PhraseQuery短语搜索

你可能对中日关系比较感兴趣,想查找挨得比较近(5个字的距离内)的文章,超过这个距离的不予考虑,你可以:

PhraseQuery query = new PhraseQuery();

query.setSlop(5);

query.add(new Term("content ", ));

query.add(new Term(content));

那么它可能搜到中日合作……”中方和日方……”,但是搜不到中国某高层领导说日本欠扁

7.1.5 PrefixQuery(前缀匹配搜索)

如果你想搜以开头的词语,你可以用PrefixQuery

PrefixQuery query = new PrefixQuery(new Term("content ", "");

7.1.6 FuzzyQuery相似搜索

FuzzyQuery用来搜索相似的term,使用Levenshtein算法。假设你想搜索跟wuzza相似的词语,你可以:

Query query = new FuzzyQuery(new Term("content", "wuzza");

你可能得到fuzzywuzzy

7.1.7 RangeQuery (范围查询

另一个常用的QueryRangeQuery,你也许想搜索时间域从2006010120060130之间的document,你可以用RangeQuery

RangeQuery query = new RangeQuery(new Term(time20060101), new Term(time20060130), true);

最后的true表示含边界。

【上篇】
【下篇】

抱歉!评论已关闭.