- 浏览: 927926 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (445)
- 备忘 (0)
- java基础 (28)
- jsp (15)
- css (4)
- javascript (30)
- struts (7)
- servlet (2)
- struts2 (7)
- jdbc (16)
- hibernate (22)
- ibatis (0)
- jpa (1)
- spring (17)
- spring定时任务 (8)
- 整合开发 (12)
- JavaArticle (0)
- php (6)
- velocity (2)
- mysql (19)
- sqlserver (52)
- oracle (23)
- lucene (49)
- ajax (13)
- dwr (5)
- JFreeChart (1)
- service (14)
- tools (18)
- c#基础 (20)
- 程序安全 (0)
- 学习网站 (1)
- 社会需求 (2)
- flash (1)
- 流媒体 (1)
- java_code (1)
- htmlparser (1)
- 速动画教程 (5)
- 设计模式 (1)
- xml操作 (2)
- uml操作 (4)
- 测试 (1)
- linux (8)
- 版本控制 (4)
- 服务器 (12)
- 安全 (6)
- 美工 (2)
最新评论
-
Zhang_amao:
我想问一下, 你用的lucene版本和highligher的版 ...
使用Lucene的Highlighter实现文件摘要的自动提取 -
wangmengfanwangzhi:
博主,你的QQ是什么啊?有关于lucene的问题想要请教啊~~ ...
Lucene下载及测试 -
cutesunshineriver:
讲得很好,理解起来很顺,对个人学习的帮助性很大,谢谢博主。
velocity入门一 -
libin2722:
我这里有一个任务调度,在晚上3点时候会自动将数据库中某表的数据 ...
Lucene-2.2.0 源代码阅读学习(16) -
greatwqs:
java -cp $JVM_ARGS $classpath ...
java的cp命令
关于Lucene检索结果的排序问题。
已经知道,Lucene的默认排序是按照Document的得分进行排序的。当检索结果集中的两个Document的具有相同的得分时,默认按照Document的ID对结果进行排序。
下面研究几种设置/改变检索结果排序的方法。
■ 改变Document的boost(激励因子)
改变boost的值实现改变检索结果集的排序,是最简单的方法,只需要在建立索引的过程中,设置指定的Document的boost值,来改变排序结果中Document位置的提前或者靠后。
根据在文章 Lucene-2.2.0 源代码阅读学习(39) 中说明的关于Lucene得分的计算,实际上改变boost的大小,会导致Document的得分的改变,从而按照Lucene默认的对检索结果集的排序方式,改变检索结果中Document的排序的提前或者靠后。在计算得分的时候,使用到了boost的值,默认boost的值为1.0,也就说默认情况下Document的得分与boost的无关的。一旦改变了默认的boost的值,也就从Document的得分与boost无关,变为相关了:boost值越大,Document的得分越高。
下面这个例子在文章 Lucene-2.2.0 源代码阅读学习(39) 中测试过,这里,在建立索引的时候,设置了一下Document的boost,看看排序结果的改变情况:
package org.shirdrn.lucene.learn.sort;
import java.io.IOException;
import java.util.Date;
import net.teamhot.lucene.ThesaurusAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.store.LockObtainFailedException;
public class AboutLuceneDefaultSort {
private String path = "F:\\index";
public void createIndex() {
IndexWriter writer;
try {
writer = new IndexWriter(path, new ThesaurusAnalyzer(), true);
Field fieldA = new Field("contents", "一人", Field.Store.YES,
Field.Index.TOKENIZED);
Document docA = new Document();
docA.add(fieldA);
docA.setBoost(0.1f); // 减小boost值
Field fieldB = new Field("contents", "一人 之交 一人之交", Field.Store.YES,
Field.Index.TOKENIZED);
Document docB = new Document();
docB.add(fieldB);
Field fieldC = new Field("contents", "一人 之下 一人之下", Field.Store.YES,
Field.Index.TOKENIZED);
Document docC = new Document();
docC.add(fieldC);
Field fieldD = new Field("contents", "一人 做事 一人当 一人做事一人当",
Field.Store.YES, Field.Index.TOKENIZED);
Document docD = new Document();
docD.setBoost(2.0f); // 提高boost值
docD.add(fieldD);
Field fieldE = new Field("contents", "一人 做事 一人當 一人做事一人當",
Field.Store.YES, Field.Index.TOKENIZED);
Document docE = new Document();
docE.add(fieldE);
writer.addDocument(docA);
writer.addDocument(docB);
writer.addDocument(docC);
writer.addDocument(docD);
writer.addDocument(docE);
writer.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (LockObtainFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
AboutLuceneDefaultSort aus = new AboutLuceneDefaultSort();
aus.createIndex(); // 建立索引
try {
String keyword = "一人";
Term term = new Term("contents", keyword);
Query query = new TermQuery(term);
IndexSearcher searcher = new IndexSearcher(aus.path);
Date startTime = new Date();
Hits hits = searcher.search(query);
TermDocs termDocs = searcher.getIndexReader().termDocs(term);
while (termDocs.next()) {
System.out
.print("搜索关键字<" + keyword + ">在编号为 " + termDocs.doc());
System.out.println(" 的Document中出现过 " + termDocs.freq() + " 次");
}
System.out
.println("********************************************************************");
for (int i = 0; i < hits.length(); i++) {
System.out.println("Document的内部编号为 : " + hits.id(i));
System.out.println("Document内容为 : " + hits.doc(i));
System.out.println("Document得分为 : " + hits.score(i));
Explanation e = searcher.explain(query, hits.id(i));
System.out.println("Explanation为 : \n" + e);
System.out.println("Document对应的Explanation的一些参数值如下: ");
System.out.println("Explanation的getValue()为 : " + e.getValue());
System.out.println("Explanation的getDescription()为 : "
+ e.getDescription());
System.out
.println("********************************************************************");
}
System.out.println("共检索出符合条件的Document " + hits.length() + " 个。");
Date finishTime = new Date();
long timeOfSearch = finishTime.getTime() - startTime.getTime();
System.out.println("本次搜索所用的时间为 " + timeOfSearch + " ms");
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
如果不设置docA.setBoost(0.1f);和docD.setBoost(2.0f);,则按照默认进行排序,即boost激励因子的值为1.0,执行后,检索结果如下所示:
词库尚未被初始化,开始初始化词库.
初始化词库结束。用时:3766毫秒;
共添加195574个词语。
搜索关键字<一人>在编号为 0 的Document中出现过 1 次
搜索关键字<一人>在编号为 1 的Document中出现过 1 次
搜索关键字<一人>在编号为 2 的Document中出现过 1 次
搜索关键字<一人>在编号为 3 的Document中出现过 2 次
搜索关键字<一人>在编号为 4 的Document中出现过 2 次
********************************************************************
Document的内部编号为 : 0
Document内容为 : Document<stored/uncompressed,indexed,tokenized<contents:一人>>
Document得分为 : 0.81767845
Explanation为 :
0.81767845 = (MATCH) fieldWeight(contents:一人 in 0), product of:
1.0 = tf(termFreq(contents:一人)=1)
0.81767845 = idf(docFreq=5)
1.0 = fieldNorm(field=contents, doc=0)
Document对应的Explanation的一些参数值如下:
Explanation的getValue()为 : 0.81767845
Explanation的getDescription()为 : fieldWeight(contents:一人 in 0), product of:
********************************************************************
Document的内部编号为 : 3
Document内容为 : Document<stored/uncompressed,indexed,tokenized<contents:一人 做事 一人当 一人做事一人当>>
Document得分为 : 0.5059127
Explanation为 :
0.5059127 = (MATCH) fieldWeight(contents:一人 in 3), product of:
1.4142135 = tf(termFreq(contents:一人)=2)
0.81767845 = idf(docFreq=5)
0.4375 = fieldNorm(field=contents, doc=3)
Document对应的Explanation的一些参数值如下:
Explanation的getValue()为 : 0.5059127
Explanation的getDescription()为 : fieldWeight(contents:一人 in 3), product of:
********************************************************************
Document的内部编号为 : 4
Document内容为 : Document<stored/uncompressed,indexed,tokenized<contents:一人 做事 一人當 一人做事一人當>>
Document得分为 : 0.5059127
Explanation为 :
0.5059127 = (MATCH) fieldWeight(contents:一人 in 4), product of:
1.4142135 = tf(termFreq(contents:一人)=2)
0.81767845 = idf(docFreq=5)
0.4375 = fieldNorm(field=contents, doc=4)
Document对应的Explanation的一些参数值如下:
Explanation的getValue()为 : 0.5059127
Explanation的getDescription()为 : fieldWeight(contents:一人 in 4), product of:
********************************************************************
Document的内部编号为 : 1
Document内容为 : Document<stored/uncompressed,indexed,tokenized<contents:一人 之交 一人之交>>
Document得分为 : 0.40883923
Explanation为 :
0.40883923 = (MATCH) fieldWeight(contents:一人 in 1), product of:
1.0 = tf(termFreq(contents:一人)=1)
0.81767845 = idf(docFreq=5)
0.5 = fieldNorm(field=contents, doc=1)
Document对应的Explanation的一些参数值如下:
Explanation的getValue()为 : 0.40883923
Explanation的getDescription()为 : fieldWeight(contents:一人 in 1), product of:
********************************************************************
Document的内部编号为 : 2
Document内容为 : Document<stored/uncompressed,indexed,tokenized<contents:一人 之下 一人之下>>
Document得分为 : 0.40883923
Explanation为 :
0.40883923 = (MATCH) fieldWeight(contents:一人 in 2), product of:
1.0 = tf(termFreq(contents:一人)=1)
0.81767845 = idf(docFreq=5)
0.5 = fieldNorm(field=contents, doc=2)
Document对应的Explanation的一些参数值如下:
Explanation的getValue()为 : 0.40883923
Explanation的getDescription()为 : fieldWeight(contents:一人 in 2), product of:
********************************************************************
共检索出符合条件的Document 5 个。
本次搜索所用的时间为 188 ms
检索结果排序为:0——3——4——1——2
如果,我们认为ID为4的Document比较重要,而ID为0的Document不重要,希望在检索的时候,ID为4的Document位置靠前一些,因为它重要,ID为0的Document靠后一些,因为它不如其它的重要,可以通过如下设置:
docA.setBoost(0.1f);
docD.setBoost(2.0f);
来改变指定的Document的boost值,从而改变这两个Document的得分,进而获取所期望的排序位置。这样设置以后,排序结果就改变了,如下所示:
词库尚未被初始化,开始初始化词库.
初始化词库结束。用时:3641毫秒;
共添加195574个词语。
搜索关键字<一人>在编号为 0 的Document中出现过 1 次
搜索关键字<一人>在编号为 1 的Document中出现过 1 次
搜索关键字<一人>在编号为 2 的Document中出现过 1 次
搜索关键字<一人>在编号为 3 的Document中出现过 2 次
搜索关键字<一人>在编号为 4 的Document中出现过 2 次
********************************************************************
Document的内部编号为 : 3
Document内容为 : Document<stored/uncompressed,indexed,tokenized<contents:一人 做事 一人当 一人做事一人当>>
Document得分为 : 1.0
Explanation为 :
1.0118254 = (MATCH) fieldWeight(contents:一人 in 3), product of:
1.4142135 = tf(termFreq(contents:一人)=2)
0.81767845 = idf(docFreq=5)
0.875 = fieldNorm(field=contents, doc=3)
Document对应的Explanation的一些参数值如下:
Explanation的getValue()为 : 1.0118254
Explanation的getDescription()为 : fieldWeight(contents:一人 in 3), product of:
********************************************************************
Document的内部编号为 : 4
Document内容为 : Document<stored/uncompressed,indexed,tokenized<contents:一人 做事 一人當 一人做事一人當>>
Document得分为 : 0.5
Explanation为 :
0.5059127 = (MATCH) fieldWeight(contents:一人 in 4), product of:
1.4142135 = tf(termFreq(contents:一人)=2)
0.81767845 = idf(docFreq=5)
0.4375 = fieldNorm(field=contents, doc=4)
Document对应的Explanation的一些参数值如下:
Explanation的getValue()为 : 0.5059127
Explanation的getDescription()为 : fieldWeight(contents:一人 in 4), product of:
********************************************************************
Document的内部编号为 : 1
Document内容为 : Document<stored/uncompressed,indexed,tokenized<contents:一人 之交 一人之交>>
Document得分为 : 0.40406102
Explanation为 :
0.40883923 = (MATCH) fieldWeight(contents:一人 in 1), product of:
1.0 = tf(termFreq(contents:一人)=1)
0.81767845 = idf(docFreq=5)
0.5 = fieldNorm(field=contents, doc=1)
Document对应的Explanation的一些参数值如下:
Explanation的getValue()为 : 0.40883923
Explanation的getDescription()为 : fieldWeight(contents:一人 in 1), product of:
********************************************************************
Document的内部编号为 : 2
Document内容为 : Document<stored/uncompressed,indexed,tokenized<contents:一人 之下 一人之下>>
Document得分为 : 0.40406102
Explanation为 :
0.40883923 = (MATCH) fieldWeight(contents:一人 in 2), product of:
1.0 = tf(termFreq(contents:一人)=1)
0.81767845 = idf(docFreq=5)
0.5 = fieldNorm(field=contents, doc=2)
Document对应的Explanation的一些参数值如下:
Explanation的getValue()为 : 0.40883923
Explanation的getDescription()为 : fieldWeight(contents:一人 in 2), product of:
********************************************************************
Document的内部编号为 : 0
Document内容为 : Document<stored/uncompressed,indexed,tokenized<contents:一人>>
Document得分为 : 0.075761445
Explanation为 :
0.076657355 = (MATCH) fieldWeight(contents:一人 in 0), product of:
1.0 = tf(termFreq(contents:一人)=1)
0.81767845 = idf(docFreq=5)
0.09375 = fieldNorm(field=contents, doc=0)
Document对应的Explanation的一些参数值如下:
Explanation的getValue()为 : 0.076657355
Explanation的getDescription()为 : fieldWeight(contents:一人 in 0), product of:
********************************************************************
共检索出符合条件的Document 5 个。
本次搜索所用的时间为 140 ms
这时,检索结果排序变为:3——4——1——2——0
可见,改变了检索结果集中Document的排序位置。
■ 改变Field的boost(激励因子)
改变Field的boost值,和改变Document的boost值是一样的。因为Document的boost是通过添加到Docuemnt中Field体现的,所以改变Field的boost值,可以改变Document的boost值。设置如下所示:
fieldA.setBoost(0.1f);
fieldD.setBoost(2.0f);
排序结果与上面设置:
docA.setBoost(0.1f);
docD.setBoost(2.0f);
对排序结果排序的改变是相同的:
3——4——1——2——0
■ 使用Sort排序工具实现排序
Lucene在查询的时候,可以通过以一个Sort作为参数构造一个检索器IndexSearcher,在构造Sort的时候,指定排序规则,例如下面的测试类:
package org.shirdrn.lucene.learn.sort;
import java.io.IOException;
import java.util.Date;
import net.teamhot.lucene.ThesaurusAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.store.LockObtainFailedException;
public class AboutLuceneSort {
private String path = "F:\\index";
public void createIndex() {
IndexWriter writer;
try {
writer = new IndexWriter(path, new ThesaurusAnalyzer(), true);
Field fieldA1 = new Field("contents", "孤身一人闯天宫,居然像旅游一下轻松,还有谁能做到这样啊?一人!", Field.Store.YES,Field.Index.TOKENIZED);
Field fieldA2 = new Field("count", "27", Field.Store.YES,Field.Index.UN_TOKENIZED);
Document docA = new Document();
docA.add(fieldA1);
docA.add(fieldA2);
Field fieldB1 = new Field("contents", "一人之交与万人之交,一人。", Field.Store.YES, Field.Index.TOKENIZED);
Field fieldB2 = new Field("count", "12", Field.Store.YES, Field.Index.UN_TOKENIZED);
Document docB = new Document();
docB.add(fieldB1);
docB.add(fieldB2);
Field fieldC1 = new Field("contents", "一人之见:千里之行,始于足下。", Field.Store.YES, Field.Index.TOKENIZED);
Field fieldC2 = new Field("count", "12", Field.Store.YES, Field.Index.UN_TOKENIZED);
Document docC = new Document();
docC.add(fieldC1);
docC.add(fieldC2);
Field fieldD1 = new Field("contents", "一人做事一人当,一人。",Field.Store.YES, Field.Index.TOKENIZED);
Field fieldD2 = new Field("count", "9", Field.Store.YES, Field.Index.UN_TOKENIZED);
Document docD = new Document();
docD.add(fieldD1);
docD.add(fieldD2);
Field fieldE1 = new Field("contents", "两人、一人、然后怎么数下去呀——晕~。",Field.Store.YES, Field.Index.TOKENIZED);
Field fieldE2 = new Field("count", "13", Field.Store.YES, Field.Index.UN_TOKENIZED);
Document docE = new Document();
docE.add(fieldE1);
docE.add(fieldE2);
writer.addDocument(docA);
writer.addDocument(docB);
writer.addDocument(docC);
writer.addDocument(docD);
writer.addDocument(docE);
writer.optimize();
writer.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (LockObtainFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
AboutLuceneSort aus = new AboutLuceneSort();
aus.createIndex(); // 建立索引
try {
String keyword = "一人";
Term term = new Term("contents", keyword);
Query query = new TermQuery(term);
IndexSearcher searcher = new IndexSearcher(aus.path);
Date startTime = new Date();
Sort sort = new Sort("count"); // 根据名称为count的Field进行排序
Hits hits = searcher.search(query,sort);
TermDocs termDocs = searcher.getIndexReader().termDocs(term);
while (termDocs.next()) {
System.out
.print("搜索关键字<" + keyword + ">在编号为 " + termDocs.doc());
System.out.println(" 的Document中出现过 " + termDocs.freq() + " 次");
}
System.out
.println("********************************************************************");
for (int i = 0; i < hits.length(); i++) {
System.out.println("Document的内部编号为 : " + hits.id(i));
System.out.println("Document内容为 : " + hits.doc(i));
System.out.println("Document得分为 : " + hits.score(i));
for(int j=0;j<hits.doc(i).getFields().size();j++){
Field field = (Field)hits.doc(i).getFields().get(j);
System.out.println("--- ---Field的name为 : " + field.name());
System.out.println("--- ---Field的StringValue为 : " + field.stringValue());
}
System.out.println("********************************************************************");
}
System.out.println("共检索出符合条件的Document " + hits.length() + " 个。");
Date finishTime = new Date();
long timeOfSearch = finishTime.getTime() - startTime.getTime();
System.out.println("本次搜索所用的时间为 " + timeOfSearch + " ms");
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用了Sort类的一个只有一个参数的构造方法:
public final void setSort(String field) {
setSort(field, false);
}
可见,实际上调用了 setSort(field, false);方法,第一个field为指定一个Field的名称,按照给Field进行排序,第二个为boolean型值,该值指定是否按照降序进行排序,默认情况下为false,表示按照升序排序,即如果按照指定的field排序是作为第一排序的,而且是按照升序排序的,第二排序默认按照Document的ID号码(编号)进行升序排序。
setSort(field, false)方法定义:
public void setSort(String field, boolean reverse) {
SortField[] nfields = new SortField[] {
new SortField(field, SortField.AUTO, reverse), SortField.FIELD_DOC };
fields = nfields;
}
在setSort(field, false)方法中,可以看到,实际上使用了SortField类实现了排序,SortField类具有更加丰富的关于排序的规则和内容。
指定:根据Field名称为“count”进行排序,这里,count是字数的意思,因此在分词的时候没有对其进行分词。期望的排序结果是,根据count,即字数进行排序,而不是根据Document的得分来排序。
运行结果如下所示:
词库尚未被初始化,开始初始化词库.
初始化词库结束。用时:3656毫秒;
共添加195574个词语。
搜索关键字<一人>在编号为 0 的Document中出现过 1 次
搜索关键字<一人>在编号为 1 的Document中出现过 1 次
搜索关键字<一人>在编号为 2 的Document中出现过 1 次
搜索关键字<一人>在编号为 3 的Document中出现过 1 次
搜索关键字<一人>在编号为 4 的Document中出现过 1 次
********************************************************************
Document的内部编号为 : 3
Document内容为 : Document<stored/uncompressed,indexed,tokenized<contents:一人做事一人当,一人。> stored/uncompressed,indexed<count:9>>
Document得分为 : 0.51104903
--- ---Field的name为 : contents
--- ---Field的StringValue为 : 一人做事一人当,一人。
--- ---Field的name为 : count
--- ---Field的StringValue为 : 9
********************************************************************
Document的内部编号为 : 1
Document内容为 : Document<stored/uncompressed,indexed,tokenized<contents:一人之交与万人之交,一人。> stored/uncompressed,indexed<count:12>>
Document得分为 : 0.35773432
--- ---Field的name为 : contents
--- ---Field的StringValue为 : 一人之交与万人之交,一人。
--- ---Field的name为 : count
--- ---Field的StringValue为 : 12
********************************************************************
Document的内部编号为 : 2
Document内容为 : Document<stored/uncompressed,indexed,tokenized<contents:一人之见:千里之行,始于足下。> stored/uncompressed,indexed<count:12>>
Document得分为 : 0.40883923
--- ---Field的name为 : contents
--- ---Field的StringValue为 : 一人之见:千里之行,始于足下。
--- ---Field的name为 : count
--- ---Field的StringValue为 : 12
********************************************************************
Document的内部编号为 : 4
Document内容为 : Document<stored/uncompressed,indexed,tokenized<contents:两人、一人、然后怎么数下去呀——晕~。> stored/uncompressed,indexed<count:13>>
Document得分为 : 0.25552452
--- ---Field的name为 : contents
--- ---Field的StringValue为 : 两人、一人、然后怎么数下去呀——晕~。
--- ---Field的name为 : count
--- ---Field的StringValue为 : 13
********************************************************************
Document的内部编号为 : 0
Document内容为 : Document<stored/uncompressed,indexed,tokenized<contents:孤身一人闯天宫,居然像旅游一下轻松,还有谁能做到这样啊?一人!> stored/uncompressed,indexed<count:27>>
Document得分为 : 0.20441961
--- ---Field的name为 : contents
--- ---Field的StringValue为 : 孤身一人闯天宫,居然像旅游一下轻松,还有谁能做到这样啊?一人!
--- ---Field的name为 : count
--- ---Field的StringValue为 : 27
********************************************************************
共检索出符合条件的Document 5 个。
本次搜索所用的时间为 125 ms
可见,是按照字数count来进行排序的:9——12——12——13——27
而此时检索结构的对应的得分分别为:0.51104903——0.35773432——0.40883923——0.25552452——0.20441961
可见,并不是按照得分的情况来进行排序的,而且,如果count的值相等,则使用默认的第二排序规则,即按照Document的ID号来排序,从上面的count=12结果可以看出。
关于Sort类,在其内部定义了6种构造方法:
public Sort()
public Sort(SortField field)
public Sort(SortField[] fields)
public Sort(String field)
public Sort(String field, boolean reverse)
public Sort(String[] fields)
可以根据不同需要指定排序的规则,按照某个或某几个Field进行排序。不带参数的构造方法public Sort(),在实例化一个Sort之后,可以非常方便的通过调用setSort方法设定排序规则,setSort有5个重载的方法:
public void setSort(SortField field)
public void setSort(SortField[] fields)
public final void setSort(String field)
public void setSort(String field, boolean reverse)
public void setSort(String[] fieldnames)
当然,public final void setSort(String field)在外部不允许直接调用了,是默认的内部使用的设置排序规则的方法。
■ 直接使用SortField实现排序
首先看一下SortField类的源代码:
package org.apache.lucene.search;
import java.io.Serializable;
import java.util.Locale;
public class SortField
implements Serializable {
// 按照Document的得分对检索结果进行排序,得分高的排序靠前
public static final int SCORE = 0;
// 按照Document的编号(ID)对检索结果进行排序,编号小的排序靠前
public static final int DOC = 1;
// 自动检测,自动选择最佳的排序方式,即按照整数类型
public static final int AUTO = 2;
// 根据词条的String串排序
public static final int STRING = 3;
// 将词条解码为整数,按照整数排序
public static final int INT = 4;
// 将词条解码为浮点数,按照浮点数排序
public static final int FLOAT = 5;
// 根据定制的排序器,实现客户化排序
public static final int CUSTOM = 9;
// IMPLEMENTATION NOTE: the FieldCache.STRING_INDEX is in the same "namespace"
// as the above static int values. Any new values must not have the same value
// as FieldCache.STRING_INDEX.
/** 根据Document的得分构造一个SortField实例 */
public static final SortField FIELD_SCORE = new SortField (null, SCORE);
/** 根据Document的编号构造一个SortField实例 */
public static final SortField FIELD_DOC = new SortField (null, DOC);
private String field;
private int type = AUTO; // defaults to determining type dynamically
private Locale locale; // defaults to "natural order" (no Locale)
boolean reverse = false; // defaults to natural order
private SortComparatorSource factory;
//★ 下面定义了8种构造SortField的方法 ★
// 以一个Field的名字的Sing串作为参数构造一个SortField
public SortField (String field) {
this.field = field.intern();
}
public SortField (String field, boolean reverse) {
this.field = field.intern();
this.reverse = reverse;
}
public SortField (String field, int type) {
this.field = (field != null) ? field.intern() : field;
this.type = type;
}
public SortField (String field, int type, boolean reverse) {
this.field = (field != null) ? field.intern() : field;
this.type = type;
this.reverse = reverse;
}
public SortField (String field, Locale locale) {
this.field = field.intern();
this.type = STRING;
this.locale = locale;
}
public SortField (String field, Locale locale, boolean reverse) {
this.field = field.intern();
this.type = STRING;
this.locale = locale;
this.reverse = reverse;
}
public SortField (String field, SortComparatorSource comparator) {
this.field = (field != null) ? field.intern() : field;
this.type = CUSTOM;
this.factory = comparator;
}
public SortField (String field, SortComparatorSource comparator, boolean reverse) {
this.field = (field != null) ? field.intern() : field;
this.type = CUSTOM;
this.reverse = reverse;
this.factory = comparator;
}
public String getField() {
return field;
}
public int getType() {
return type;
}
public Locale getLocale() {
return locale;
}
public boolean getReverse() {
return reverse;
}
public SortComparatorSource getFactory() {
return factory;
}
public String toString() {
StringBuffer buffer = new StringBuffer();
switch (type) {
case SCORE: buffer.append("<score>");
break;
case DOC: buffer.append("<doc>");
break;
case CUSTOM: buffer.append ("<custom:\"" + field + "\": "
+ factory + ">");
break;
default: buffer.append("\"" + field + "\"");
break;
}
if (locale != null) buffer.append ("("+locale+")");
if (reverse) buffer.append('!');
return buffer.toString();
}
}
从上面代码中,可以看出,指定了一种排序的type,这个type对排序的效率是至关重要的,涉及到一个比较的问题。从代码中:
private int type = AUTO;
指定了默认的类型,而AUTO定义如下:
public static final int AUTO = 2;
即按照整数类型,使用整数类型作为排序的type,在进行排序时,效率远远比String类型要高得多。
构造一个SortField实例之后,通过Sort类的setSort方法可以设定详细的排序规则,从而实现对检索结果的排序。
例如:
1、构造一个没有参数的Sort:Sort sort = new Sort();
2、构造一个SortField:SortField sf = new SortField("count",SortField.AUTO,true);
3、使用setSort方法:sort .setSort(sf);
4、构造一个检索器:IndexSearcher is = new IndexSearcher("F:\\index");
5、调用带Sort参数的search检索方法:Hits hits = is.search(query,sort);
这是一个最简单的设置排序的步骤,可以根据SortField的构造方法,构造更加复杂的排序规则。
发表评论
-
创建索引的时候出现的错误
2010-01-04 10:13 1701<OFMsg>251658517"1&q ... -
SQLServer2005获取大数据集时内存不足的解决办法
2009-02-12 10:59 1987今天在修改search的建立索引的程序的时候,发现了这个错误 ... -
使用Lucene的Highlighter实现文件摘要的自动提取
2009-02-06 16:52 6646使用Lucene自带的Highlighter就可以实现对原始文 ... -
Lucene倒排索引原理
2009-02-06 16:08 1153Lucene是一个高性能的java全文检索工具包,它使用的是倒 ... -
Lucene 2.2.0发布自带的HTMLParser的使用
2009-02-06 16:00 2536Lucene 2.2.0发行包中自带 ... -
Lucene关键字高亮显示
2009-02-06 15:53 2375在Lucene的org.apache.lucene.s ... -
Lucene-2.2.0 源代码阅读学习(42)
2009-02-06 15:46 1332关于Hits类。这个Hits类 ... -
Lucene-2.2.0 源代码阅读学习(41)
2009-02-06 15:40 1109当执行Hits htis = search(query);这一 ... -
Lucene-2.2.0 源代码阅读学习(39)
2009-02-06 15:31 1118关于Lucene得分的计算。 在IndexSearcher类中 ... -
Lucene-2.2.0 源代码阅读学习(38)
2009-02-06 15:13 1129关于QueryParser。 QueryParser是用来解析 ... -
Lucene-2.2.0 源代码阅读学习(37)
2009-02-06 15:06 1065关于MultiTermQuery查询。 这里研究继承自Mult ... -
Lucene-2.2.0 源代码阅读学习(36)
2009-02-06 15:05 1017关于MultiTermQuery查询。 这里研究FuzzyQu ... -
Lucene-2.2.0 源代码阅读学习(35)
2009-02-06 15:03 941于MultiPhraseQuery(多短语查询)。 Multi ... -
Lucene-2.2.0 源代码阅读学习(34)
2009-02-06 15:02 971关于PhraseQuery。 PhraseQuery查询是将多 ... -
Lucene-2.2.0 源代码阅读学习(33)
2009-02-06 15:01 996关于范围查询RangeQuery。 ... -
Lucene-2.2.0 源代码阅读学习(32)
2009-02-06 15:00 889关于SpanQuery(跨度搜索),它是Query的子类,但是 ... -
Lucene-2.2.0 源代码阅读学习(31)
2009-02-06 14:58 947关于前缀查询PrefixQuery(前缀查询)。 准备工作就是 ... -
Lucene-2.2.0 源代码阅读学习(30)
2009-02-06 14:57 755关于Query的学习。 主要使用TermQuery和Boole ... -
Lucene-2.2.0 源代码阅读学习(29)
2009-02-06 14:54 1158关于IndexSearcher检索器。 ... -
Lucene-2.2.0 源代码阅读学习(28)
2009-02-06 14:48 1284关于检索的核心IndexSearcher类。 IndexSea ...
相关推荐
lucene-analyzers-2.2.0.jarlucene-analyzers-2.2.0.jarlucene-analyzers-2.2.0.jarlucene-analyzers-2.2.0.jarlucene-analyzers-2.2.0.jarlucene-analyzers-2.2.0.jarlucene-analyzers-2.2.0.jarlucene-analyzers-...
标题中的"lucene-2.2.0zip"指的是Lucene的2.2.0版本,这是一个较早的版本,对于学习和理解Lucene的基础概念非常有帮助。 Lucene 2.2.0的主要特性包括: 1. **全文检索**:Lucene支持对文档内容进行全文检索,允许...
lucene-highlighter-2.2.0.jarlucene-highlighter-2.2.0.jarlucene-highlighter-2.2.0.jarlucene-highlighter-2.2.0.jarlucene-highlighter-2.2.0.jarlucene-highlighter-2.2.0.jarlucene-highlighter-2.2.0.jar
《Lucene-2.3.1 源代码阅读学习》 Lucene是Apache软件基金会的一个开放源码项目,它是一个高性能、全文本搜索库,为开发者提供了在Java应用程序中实现全文检索功能的基础架构。本篇文章将深入探讨Lucene 2.3.1版本...
《深入解析Lucene高亮显示源码:剖析`lucene-highlighter-2.2.0-src.zip`》 Lucene,作为一个开源全文检索库,以其高效、灵活的特点在信息检索领域广泛应用。在处理搜索结果时,为了提升用户体验,通常会采用高亮...
《深入剖析Lucene 2.2.0源代码》 Lucene是一款强大的开源全文搜索引擎库,由Apache软件基金会开发并维护。它为Java开发者提供了一种高性能、可扩展的文本检索核心工具。本文将深入探讨Lucene 2.2.0版本的源代码,...
在前面Lucene-2.2.0 源代码阅读学习(1)中,根据Lucene提供的一个Demo,详细分析研究一下索引器org.apache.lucene.index.IndexWriter类,看看它是如果定义的,掌握它建立索引的机制。 通过IndexWriter类的实现源代码...
赠送源代码:lucene-analyzers-smartcn-7.7.0-sources.jar; 赠送Maven依赖信息文件:lucene-analyzers-smartcn-7.7.0.pom; 包含翻译后的API文档:lucene-analyzers-smartcn-7.7.0-javadoc-API文档-中文(简体)版....
赠送源代码:lucene-core-7.7.0-sources.jar; 赠送Maven依赖信息文件:lucene-core-7.7.0.pom; 包含翻译后的API文档:lucene-core-7.7.0-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.apache.lucene:lucene...
- 通过阅读源代码,可以理解Lucene的内部工作原理,如如何构建索引、执行查询等。 - 分析器部分的源码有助于了解文本预处理过程,包括分词、去除停用词等。 - 探究查询解析器的实现,掌握如何将自然语言转化为...
赠送源代码:lucene-analyzers-common-6.6.0-sources.jar; 赠送Maven依赖信息文件:lucene-analyzers-common-6.6.0.pom; 包含翻译后的API文档:lucene-analyzers-common-6.6.0-javadoc-API文档-中文(简体)版.zip;...
这是一个java开发用的.jar文件,用它和Lucene-core-2.0.0.jar可以实现搜索引擎
赠送源代码:lucene-core-7.2.1-sources.jar; 赠送Maven依赖信息文件:lucene-core-7.2.1.pom; 包含翻译后的API文档:lucene-core-7.2.1-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.apache.lucene:lucene...
赠送源代码:lucene-suggest-6.6.0-sources.jar; 赠送Maven依赖信息文件:lucene-suggest-6.6.0.pom; 包含翻译后的API文档:lucene-suggest-6.6.0-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.apache....
赠送源代码:lucene-backward-codecs-7.3.1-sources.jar; 赠送Maven依赖信息文件:lucene-backward-codecs-7.3.1.pom; 包含翻译后的API文档:lucene-backward-codecs-7.3.1-javadoc-API文档-中文(简体)-英语-对照...
赠送源代码:lucene-core-6.6.0-sources.jar; 赠送Maven依赖信息文件:lucene-core-6.6.0.pom; 包含翻译后的API文档:lucene-core-6.6.0-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.apache.lucene:lucene...
赠送源代码:lucene-spatial-extras-7.3.1-sources.jar; 赠送Maven依赖信息文件:lucene-spatial-extras-7.3.1.pom; 包含翻译后的API文档:lucene-spatial-extras-7.3.1-javadoc-API文档-中文(简体)-英语-对照版....
赠送源代码:lucene-memory-6.6.0-sources.jar; 赠送Maven依赖信息文件:lucene-memory-6.6.0.pom; 包含翻译后的API文档:lucene-memory-6.6.0-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.apache.lucene:...
赠送源代码:lucene-suggest-7.7.0-sources.jar; 赠送Maven依赖信息文件:lucene-suggest-7.7.0.pom; 包含翻译后的API文档:lucene-suggest-7.7.0-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.apache....
赠送源代码:lucene-analyzers-smartcn-7.7.0-sources.jar; 赠送Maven依赖信息文件:lucene-analyzers-smartcn-7.7.0.pom; 包含翻译后的API文档:lucene-analyzers-smartcn-7.7.0-javadoc-API文档-中文(简体)-英语...