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

本文介绍了 Lucene.NET 的基本使用方法,涵盖了建立索引和进行搜索两大核心功能。详细解释了 Document、Field 和 IndexWriter 等关键概念,并探讨了索引的优化及搜索技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

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

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

*Field:Document中的一个字段,相当于数据库中的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.1Field的解释

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

Field(Stringname,byte[]value,Field.Storestore)

Field(Stringname,Readerreader)

Field(Stringname,Readerreader,Field.TermVectortermVector)

Field(Stringname,Stringvalue,Field.Storestore,Field.Indexindex)

Field(Stringname,Stringvalue,Field.Storestore,Field.Indexindex,Field.TermVectortermVector)

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

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

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

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

Field.Index.TOKENIZED:分词索引。

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

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

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

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

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

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

Field.Store.COMPRESS压缩存储;

*termVector是Lucene1.4.3新增的它提供一种向量机制来进行模糊查询,很少用。

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

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

Field(Stringname,Readerreader)

Field(Stringname,Readerreader,Field.TermVectortermVector)

*限制Field的长度:

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

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

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

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

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

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

reader.deleteDocument(newTerm("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(intn):返回第n个文档

iterator():返回一个迭代器

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

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

1.搜集关键字keyword

2.创建索引IndexWriter

3.进行索引IndexRead

Lucene.NET

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

Score=Score*Boost

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

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

Documentdocument=newDocument();
switch(vip)
{
caseVIP.Gold:document.SetBoost(2F);break;
caseVIP.Argentine:document.SetBoost(1.5F);break;
}

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

Lucene.NET

Refurbishtime职位刷新时间

Sortsort=newSort(newSortField("refurbishtime",SortField.AUTO,true));//特注:true降幂排序false升幂排序

publicconstintSCORE=0;//相关度

publicconstintDOC=1;//文挡号

publicconstintAUTO=2;//自动识别

publicconstintSTRING=3;//字符型

publicconstintINT=4;//int

publicconstintFLOAT=5;//float

publicconstintCUSTOM=9;//自定义

Lucene.NET关键字高亮

--------luceneSOSO.rar

Lucene.NET添加索引

--------luceneSOSO.rar

Lucene.NET更新索引

--------luceneSOSO.rar

Lucene.NET删除索引

--------luceneSOSO.rar

Lucene.NET

7如何搜索

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

7.1各种各样的Query

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

7.1.1TermQuery

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

Termt=newTerm("content","lucene");

Queryquery=newTermQuery(t);

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

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

或者
TermQuerytermQuery1=newTermQuery(newTerm("content","java");
TermQuerytermQuery2=newTermQuery(newTerm("content","perl");
BooleanQuerybooleanQuery=newBooleanQuery();
booleanQuery.add(termQuery1,BooleanClause.Occur.SHOULD);
booleanQuery.add(termQuery2,BooleanClause.Occur.SHOULD);

7.1.3WildcardQuery通配符搜索

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

Queryquery=newWildcardQuery(newTerm("content","use*");

7.1.4PhraseQuery短语搜索

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

PhraseQueryquery=newPhraseQuery();

query.setSlop(5);

query.add(newTerm("content",));

query.add(newTerm(content,));

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

7.1.5PrefixQuery(前缀匹配搜索)

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

PrefixQueryquery=newPrefixQuery(newTerm("content","中");

7.1.6FuzzyQuery相似搜索

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

Queryquery=newFuzzyQuery(newTerm("content","wuzza");

你可能得到fuzzywuzzy

7.1.7RangeQuery范围查询

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

RangeQueryquery=newRangeQuery(newTerm(time,20060101),newTerm(time,20060130),true);

最后的true表示含边界。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值