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分数
    执行此操作。