I.Sorting search results
在Lucene中有两种特别的类型是用来排序的:Score和Index order
要排序结果 可以使用IndexSearcher的重载serach函数,提供一个Sort参数.看个例子.SortingExample.java
01
package
lia.advsearching;
02
03
import
org.apache.commons.lang.StringUtils;
04
import
org.apache.lucene.document.Document;
05
import
org.apache.lucene.index.Term;
06
import
org.apache.lucene.search.Hits;
07
import
org.apache.lucene.search.IndexSearcher;
08
import
org.apache.lucene.search.Query;
09
import
org.apache.lucene.search.RangeQuery;
10
import
org.apache.lucene.search.Sort;
11
import
org.apache.lucene.search.SortField;
12
import
org.apache.lucene.store.Directory;
13
import
org.apache.lucene.store.FSDirectory;
14
15
import
java.io.IOException;
16
import
java.text.DecimalFormat;
17
18
public class
SortingExample {
19
private
Directory directory;
20
21
public
SortingExample(Directory directory) {
22
this
.directory = directory;
23
}
24
//
显示搜索结果
25
public void
displayHits(Query query, Sort sort)
26
throws
IOException {
27
IndexSearcher searcher =
new
IndexSearcher(directory);
28
29
Hits hits = searcher.search(query, sort); //
安
sort
来排序搜索结果
30
31
System.out.println(
"\nResults for: "
+
32
query.toString() +
" sorted by "
+ sort); //
打印
query
和
sort
33
34
System.out.println(StringUtils.rightPad(
"Title"
,
30
) + //
使用
StringUtils(
来自
Apache commons)
打印结果
35
StringUtils.rightPad(
"pubmonth"
,
10
) +
36
StringUtils.center(
"id"
,
4
) +
37
StringUtils.center(
"score"
,
15
));
38
39
DecimalFormat scoreFormatter =
new
DecimalFormat(
"0.######"
);
40
for
(
int
i =
0
; i < hits.length(); i++) { //
打印结果
41
Document doc = hits.doc(i);
42
System.out.println(
43
StringUtils.rightPad(
44
StringUtils.abbreviate(doc.get(
"title"
),
29
),
30
) +
45
StringUtils.rightPad(doc.get(
"pubmonth"
),
10
) +
46
StringUtils.center(
""
+ hits.id(i),
4
) +
47
StringUtils.leftPad(
48
scoreFormatter.format(hits.score(i)),
12
));
49
System.out.println(
" "
+ doc.get(
"category"
));
50
// System.out.println(searcher.explain(query, hits.id(i)));
51
}
52
53
searcher.close();
54
}
55
56
public static void
main(String[] args)
throws
Exception {
57
Term earliest =
new
Term(
"pubmonth"
,
"190001"
);
58
Term latest =
new
Term(
"pubmonth"
,
"201012"
);
59
RangeQuery allBooks =
new
RangeQuery(earliest, latest,
true
); // query
60
61
String indexDir = System.getProperty(
"index.dir"
); // index
的目录
62
63
FSDirectory directory =
64
FSDirectory.getDirectory(indexDir,
false
);
65
SortingExample example =
new
SortingExample(directory);
66
67
example.displayHits(allBooks, Sort.RELEVANCE); //
使用
Lucene
默认的排序
68
69
example.displayHits(allBooks, Sort.INDEXORDER); //
根据
IndexOrder
排序
70
71
example.displayHits(allBooks,
new
Sort(
"category"
)); //
根据
category
排序
72
73
example.displayHits(allBooks,
new
Sort(
"pubmonth"
,
true
)); //
根据
pubmonth
排序
74
75
example.displayHits(allBooks,
76
new
Sort(
new
SortField[]{
77
new
SortField(
"category"
),
78
SortField.FIELD_SCORE,
79
new
SortField(
"pubmonth"
, SortField.INT,
true
)
80
})); ///
81
82
83
example.displayHits(allBooks,
new
Sort(
new
SortField[] {SortField.FIELD_SCORE,
new
SortField(
"category"
)}));
84
}
85
}
当sort 参数是null ,new Sort(),和Sort.RELEVANCE 时,使用的是Lucene的默认排序(按照Relevance的递减排序), 默认搜索的结果如下:
先按照Score递减排序 如果Score相同则按照Docnum 递增排序.
If the order documents were indexed is relevant, you can use Sort.INDEXORDER.
下面是其输出结果:(安装ID来排序)
要利用Field排序,该field要满足第二章排序(参考我的Blog上的内容)的要求. 下面是使用category field的输出.
默认的field排序是按照自然排序,利用Sort的重载函数,提供一个reverse参数可以改变顺序.结果如下:
example.displayHits(allBooks, new Sort("pubmonth", true)); 提供了true参数.
还可以根据多个Field排序. 用法如下:
example.displayHits(allBooks,
new Sort(new SortField[]{
new SortField("category"),
SortField.FIELD_SCORE,
new SortField("pubmonth", SortField.INT, true)
}));
margin: 5pt 6