Lucene按分数排序,然后修改日期
我的文档中有三个字段Lucene按分数排序,然后修改日期,lucene,Lucene,我的文档中有三个字段 头衔 内容 修改日期 因此,当我搜索一个术语时,它是根据得分排序的结果给出的 现在,我想根据modifiedDate对相同分数的结果进行进一步排序,即在顶部显示具有相同分数的最新文档 我试着按分数排序,修改日期,但不起作用。谁能给我指出正确的方向 您可以使用自定义收集器来解决此问题。它将按分数,然后按时间戳对结果进行排序。在此收集器中,您应该检索时间戳值以进行第二次排序。见下面的课程 公共类CustomCollector扩展了TopDocsCollector{ 记分单和时间
术语时,它是根据得分排序的结果给出的
现在,我想根据modifiedDate
对相同分数的结果进行进一步排序,即在顶部显示具有相同分数的最新文档
我试着按分数排序,修改日期,但不起作用。谁能给我指出正确的方向 您可以使用自定义收集器来解决此问题。它将按分数,然后按时间戳对结果进行排序。在此收集器中,您应该检索时间戳值以进行第二次排序。见下面的课程
公共类CustomCollector扩展了TopDocsCollector{
记分单和时间pqTop;
//防止实例化
公共CustomCollector(整数){
super(新的HitQueueWithTime(numHits,true));
//HitQueue实现getSentinelObject以返回ScoreDoc,因此我们知道
//此时top()已初始化。
pqTop=pq.top();
}
@凌驾
公共LeafCollector getLeafCollector(LeafReaderContext上下文)
抛出IOException{
final int docBase=context.docBase;
最终数值DocValues modifiedDate=
getNumeric(context.reader(),“modifiedDate”);
返回新的LeafCollector(){
记分员记分员;
@凌驾
公共无效设置记分器(记分器记分器)抛出IOException{
this.scorer=记分员;
}
@凌驾
公共void collect(int doc)引发IOException{
浮动分数=记分员。分数();
//此收集器无法处理这些分数:
断言分数!=Float.NEGATIVE_无穷大;
assert!Float.isNaN(分数);
totalHits++;
如果(得分hitB.doc:
hitA.timestamp
在此之后,您可以根据需要搜索结果。请参见下面的示例
公共类搜索测试{
公共静态void main(字符串[]args)引发IOException{
IndexWriterConfig IndexWriterConfig=新IndexWriterConfig(新标准分析器());
目录目录=新的RAMDirectory();
IndexWriter IndexWriter=新的IndexWriter(目录,indexWriterConfig);
addDoc(indexWriter,“w1”,1000);
addDoc(indexWriter,“w1”,3000);
addDoc(indexWriter,“w1”,500);
addDoc(indexWriter,“w1 w2”,1000);
addDoc(indexWriter,“w1 w2”,3000);
addDoc(indexWriter,“w1 w2”,2000年);
addDoc(indexWriter,“w1 w2”,5000);
final IndexReader IndexReader=DirectoryReader.open(indexWriter,false);
IndexSearcher IndexSearcher=新的IndexSearcher(indexReader);
BooleanQuery=新建BooleanQuery();
add(新术语query(新术语(“desc”,“w1”))、BooleanClause.occure.SHOULD);
add(新术语query(新术语(“desc”,“w2”))、BooleanClause.occure.SHOULD);
CustomCollector结果=新CustomCollector(100);
搜索(查询、结果);
TopDocs搜索=results.TopDocs();
for(ScoreDoc sd:search.scoreDocs){
Document Document=indexReader.Document(sd.doc);
System.out.println(document.getField(“desc”).stringValue()+“”+((ScoreDocWithTime)sd).timestamp);
}
}
私有静态void addDoc(IndexWriter IndexWriter,String decs,long modifiedDate)引发IOException{
单据单据=新单据();
新增单据(新增文本字段(“desc”,decs,Field.Store.YES));
doc.add(新的LongField(“modifiedDate”,modifiedDate,Field.Store.YES));
添加文件(新的NumericDocValuesField(“modifiedDate”,modifiedDate));
indexWriter.addDocument(文档);
}
}
程序将输出以下结果
w1 w2 5000
w1 w2 3000
w1 w2 2000
w1 w2 1000
w1 3000
w1 1000
W1500
注意:Lucene 5.1的此解决方案可以通过定义排序来完成:
Sort Sort=新排序(
SortField.FIELD_得分,
新的SortField(“myDateField”,SortField.Type.STRING));
search(myQuery、numHits、sort);
这里有两个可能的陷阱:
- 你应该确保你的日期是以可搜索、可排序的形式编入索引的。一般来说,最好的方法是使用
- 用于排序的字段必须编制索引,不应进行分析(例如,a
StringField
),是否存储取决于您
因此,添加日期字段可能类似于:
Field dateField=new StringField(
“myDateField”,
DateTools.DateToString(myDateInstance,DateTools.Resolution.MINUTE),
Field.Store.YES);
document.add(日期字段);
注意:您还可以使用Date.getTime()将日期索引为数字字段
。我更喜欢DateTools
string方法,因为它提供了一些更好的工具来处理它们,特别是在精度方面,但任何一种方法都可以工作。排序在这里都不适合,因为它会在最上面显示最近的文档。如前所述,我们需要首先根据相关性对文档进行排序,如果文档得分相等然后按时间排序。@Alexander Kuznetsov-请参阅我答案中的排序声明。ctor中的第一个SortField
,因此它将首先按分数排序,然后按日期字段排序。谢谢澄清。您知道如何反转SortField.field\u score
?通过添加布尔反转,新的SortField
很容易。但是我不知道如何为字段\u分数
执行此操作。