Lucene自定义排序机制问题研究

时间:2022-07-07 05:20:47

Lucene自定义排序机制问题研究

摘 要

本文设计了一个Lucene样例程序,实现了完整的索引和搜索功能,并在搜索功能里自定义了多种排序方法,同时分析了核心源代码,上述分析及源代码对相关的工程实践有着较大的参考价值。

【关键词】Lucene 排序 搜索

1 问题的提出

Lucene是一个开源的全文检索引擎架构,由Apache软件基金会支持和提供,它提供了完整的查询引擎和索引引擎,软件开发人员可以方便地在目标系统中实现全文检索功能,或者以此为基础建立完整的全文检索引擎。最近几年来,Lucene成为最受欢迎的免费Java信息检索程序库。

当Lucene返回匹配搜索条件的文档时,一般是按照默认评分对文档进行排序的。但是有时候,我们可能需要按照其它标准对搜索结果进行排序,这就需要自定义排序规则,下面借助一个案例,深入探讨Lucene的自定义排序机制。

2 建立索引并自定义排序规则

2.1 建立索引

首先,准备要索引的内容,本案例拟索引书籍信息,具体包括书名(name)、作者(author)、类型(name)、出版社(pub)、价格(price)和出版日期(date)等内容,定义如下数组:

String[] names={"红楼梦","水浒传","三国演义","西游记","国富论"};

String[] authors={"曹雪芹","施耐庵","罗贯中","吴承恩","亚当斯密"};

String[] types={"小说","小说","小说","小说","经济"};

String[] pubs={"人民文学出版社","人民文学出版社","光明日报出版社","人民文学出版社","上海三联书店"};

double[] prices={44.30,35.10,29.20,32.80, 29.40};

String[] dates={"2000-5-1","1997-1-1", "2000-5-1","1980-5-1","2009-3-1"};

其次,决定索引的存储位置,鉴于本案例数据少,可将索引直接放在内存中,因此创建如下Directory对象。

directory=new RAMDirectory();

其中,directory是个类级实例变量,表示索引的存储位置。

再次,创建IndexWriter对象,用以创建和维护索引。

IndexWriterConfig config=new IndexWriterConfig(Version.LUCENE_4_10_2,

new SmartChineseAnalyzer());

IndexWriter writer=new IndexWriter(directory, config);

其中,IndexWriterConfig对象持有创建IndexWriter对象时的所有配置信息,Version指明了Lucene的版本号,SmartChineseAnalyzer对象是Lucene提供的中文分析器,用来在索引期间对中文内容进行分词。

最后,通过循环索引书籍信息。

for(int i=0;i<names.length;i++)

{

Document doc=new Document();

doc.add(new StringField("name",names[i],Store.YES));

doc.add(new StringField("author",authors[i],Store.YES));

doc.add(new StringField("type",types[i],Store.YES));

doc.add(new StringField("pub",pubs[i], Store.YES));

doc.add(new StringField("date",dates[i],Store.YES));

doc.add(new DoubleField("price", prices[i],Store.YES));

writer.addDocument(doc);

}

mit();

2.2 自定义不同排序标准进行搜索

首先,创建IndexSearcher对象,这个对象通过IndexReader实现对索引的搜索功能。

IndexReader reader=DirectoryReader.open(directory);

IndexSearcher searcher=new IndexSearcher(reader);

其中,IndexReader是一个抽象类,它提供了在任意时间点访问索引的接口,

其次,创建搜索条件。

Term term=new Term("type", "小说");

Query query=new TermQuery(term);

其中,Term代表文本中的一个词,它是搜索的关键字,TermQuery则是根据搜索关键字创建的查询。

再次,自定义排序规则。默认情况下,Lucene返回匹配搜索条件的文档,是按照文档评分的高低,进行降序排列的。评分越高,说明与搜索条件匹配的越好,显示顺序越靠前。不过,实际应用中,可能会根据文档的不同域,对文档顺序进行调整。

如果使用默认的关联性评分排序,则编写如下代码:

Sort sort=new Sort();

如果根据单个域,进行降序或升序排列,则编写如下代码:

//根据出版日期,降序排列

Sort sort=new Sort(new SortField("date", Type.STRING,true));

//根据书籍价格,升序排序

Sort sort=new Sort(new SortField("price", Type.DOUBLE,false));

如果根据单个域排序,出现数据相同的情况,也可以根据多个域排序,代码如下:

//多个域排序,根据出版日期降序排列,如果日期相同,再根据作者名字降序排列

Sort sort=new Sort(new SortField("date", Type.STRING, true),new SortField("author",

Type.STRING, true));

最后,根据搜索条件和排序规则,实现搜索功能。

TopDocs hits=searcher.search(query, 10,sort);

System.out.println("找到相关结果"+hits.totalHits+"个");

System.out.println("id\t书名\t作者\t类型\t出版社\t\t出版日期\t\t价格");

for(ScoreDoc sd:hits.scoreDocs)

{

Document doc=searcher.doc(sd.doc);

System.out.println(sd.doc+"\t"+doc.get("name")+"\t"+doc.get("author")+

"\t"+doc.get("type")+"\t"+doc.get("pub")+

"\t"+doc.get("date")+"\t"+doc.get("price"));

}

其中,TopDocs表示搜索命中的所有文档,ScoreDoc则表示TopDocs中的一个命中文档,Document表示一个文档,它通过get方法就可以获取指定域的内容。

下面我们观察一下,当自定义一个多域排序规则时,上述程序的运行结果。

找到相关结果4个,如表1所示。

从表1的结果可以看出,匹配文档首先按照出版日期进行了降序排列,日期相同的,则按照作者进行了降序排列。

3 总结

Lucene支持完整的索引和搜索功能,根据搜索条件返回匹配文档时,一定要选择合适的排序规则,这样才能满足不同用户的搜索需求,使得最满足要求的文档排在最前,从而提高用户体验的满意度。

参考文献

[1]Michael McCandless.Lucene In Action[M].北京:人民邮电出版社,2011.

作者简介

刘妍(1978-),黑龙江省哈尔滨市人。现为黑龙江司法警官职业学院信息技术应用系副教授,擅长企业级软件开发。

作者单位

黑龙江司法警官职业学院信息技术应用系 黑龙江省哈尔滨市 150080

上一篇:主题论坛: 2015 拐点与服务 下一篇:电广传媒发起设立50亿互联网新媒体产业基金