开篇:润墨网以专业的文秘视角,为您筛选了一篇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