- 浏览: 284697 次
- 性别:
- 来自: 湖南岳阳
最新评论
-
ternus:
兄弟,我用boboBrowse 也遇到了排序的问题,上线了讨论 ...
lucene 分组 bobo-Browse 排序的问题 -
luli0822:
Awesome bookmarks of those guru ...
流行的jQuery信息提示插件(jQuery Tooltip Plugin) -
shenbai:
如果你要在前台运行,你应该run得是ElasticSearch ...
ElasticSearch 源码分析 环境入门 -
cl1154781231:
<s:peroperty value="#at ...
关于Struts2中标签的一些心得 -
RonQi:
转载的吗?http://blog.csdn.net/stray ...
利用bobo-browse 实现lucene的分组统计功能
关于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-02-25 10:22 876一、总论 根据http://lucene.apache.or ... -
lucene 分组 bobo-Browse 排序的问题
2010-02-01 16:18 2224今天碰到了一个问题,用bobo分组后对价格升序 居然100 ... -
开源搜索引擎
2010-02-01 14:31 1695开放源代码搜索引擎为 ... -
lucene中的filter器群组及其缓存大盘点
2010-01-20 23:18 1202lucene中的filter其实并不起眼,大家对其对性能的影响 ... -
利用bobo-browse 实现lucene的分组统计功能
2010-01-18 17:50 2940bobo-browse 是一用java写的lucene扩展组件 ... -
lucene Field部分参数设置含义
2009-11-07 17:51 1249<script type="text/ja ... -
刚下载,开始学习lucene时看的文章
2009-09-04 18:43 1432Lucene 2.0.0下载安装及测试 【下载】 下载链接 ... -
Lucene-2.3.1 阅读学习(42)
2009-09-04 18:42 945关于Hits类。 这个Hits类 ... -
Lucene 2.3.1 阅读学习(41)
2009-09-04 18:42 1412当执行Hits htis = search(query);这一 ... -
Lucene-2.3.1 源代码阅读学习(39)
2009-09-04 18:41 1155关于Lucene得分的计算。 在IndexSearcher类 ... -
Lucene-2.3.1 源代码阅读学习(39)
2009-09-04 18:38 565关于Lucene得分的计算。 在IndexSearcher类 ... -
Lucene-2.3.1 源代码阅读学习(38)
2009-09-04 18:38 922关于QueryParser。 QueryParser是用来解 ... -
Lucene-2.3.1 源代码阅读学习(37)
2009-09-04 18:37 631关于MultiTermQuery查询。 这里研究继承自Mul ... -
Lucene-2.3.1 源代码阅读学习(36)
2009-09-04 18:37 808关于MultiTermQuery查询。 ... -
Lucene-2.3.1 源代码阅读学习(35)
2009-09-04 18:36 845关于MultiPhraseQuery(多短语查询)。 Mul ... -
Lucene-2.3.1 源代码阅读学习(34)
2009-09-04 18:36 640关于PhraseQuery。 PhraseQuery查询是将 ... -
Lucene-2.3.1 源代码阅读学习(33)
2009-09-04 18:35 870关于范围查询RangeQuery。 ... -
Lucene-2.3.1 源代码阅读学习(32)
2009-09-04 18:35 1156关于SpanQuery(跨度搜索),它是Query的子类,但是 ... -
Lucene-2.3.1 源代码阅读学习(31)
2009-09-04 18:34 873关于前缀查询PrefixQuery(前缀查询)。 准备工作就 ... -
Lucene-2.3.1 源代码阅读学习(30)
2009-09-04 18:34 1064关于Query的学习。 主要使用TermQuery和Bool ...
相关推荐
《Lucene-2.3.1 源代码阅读学习》 Lucene是Apache软件基金会的一个开放源码项目,它是一个高性能、全文本搜索库,为开发者提供了在Java应用程序中实现全文检索功能的基础架构。本篇文章将深入探讨Lucene 2.3.1版本...
总而言之,Lucene 2.3.1作为一款经典的搜索引擎框架,它的源代码不仅提供了学习信息检索理论的机会,也是实践和掌握Java编程、数据结构和算法的宝贵资源。通过对压缩包中的文件进行分析,开发者可以深入了解Lucene的...
通过深入学习和理解这些源代码文件,开发者可以更好地掌握 Lucene.Net 的核心功能,如索引构建、查询解析、搜索排序、分词和性能优化。这有助于在实际项目中实现高效、精确的全文搜索引擎。同时,研究源码也能提升对...
4.其中src文件夹内为全部源代码,WebRoot为web应用部署文件 5.本系统的最小有效组件集合为:(约定:以下“*.*”均表示目录下的所有单独文件,不包括文件夹,而“/s”则表示所有的文件夹及其内部内容) src\*.* /s ...
### Lucene+Solor知识点概述 #### 一、搜索引擎基础理论 **1.1 Google神话** - **起源与发展:** - Google成立于1998年,由Larry Page和Sergey Brin创立。 - 初期以PageRank算法为核心,有效解决了当时互联网...
- **开源协议**:使用Apache License 2.0协议,源代码完全开源,没有商业限制。 - **技术栈成熟**:使用当前最主流的J2EE开发框架和技术,易于学习和维护。 - **数据库支持广泛**:支持多种数据库,如MySQL、Oracle...
- **1.4.1 目录结构说明**:Solr项目的目录结构清晰,主要包括src/main/java下的源代码、src/main/resources下的资源文件等。 - **1.4.2 Solrhome说明**:Solrhome是Solr实例的工作目录,包含了索引数据、配置文件等...
- **1.4.1 目录结构说明**:Solr的核心源码主要由几个关键部分组成,如`src/main/java`包含Java源代码,`src/main/resources`存放配置文件等。 - **1.4.2 Solrhome说明**:Solrhome是Solr运行时使用的根目录,包含了...
CAS (Central Authentication Service) 是一种开放源代码的单点登录协议和服务实现,主要用于Web应用的安全身份验证。CAS支持跨域的身份验证管理,允许用户通过一个中心服务进行一次登录即可访问多个应用系统。 **...
2.3.1. 保存 ACL 数据确保持久性 2.3.2. 使用声明(Assert)来编写条件性的 ACL 规则 3. Zend_Auth 3.1. 简介 3.1.1. 适配器 3.1.2. 结果 3.1.3. 身份的持久(Persistence) 3.1.3.1. 在PHP Session 中的缺省...