【问题标题】:Sortiing String field alphabetically in Lucene 5.0在 Lucene 5.0 中按字母顺序排序字符串字段
【发布时间】:2015-06-24 01:47:54
【问题描述】:

我在 Lucene 5.0 中对字符串字段进行排序时遇到问题。显然,自 Lucene 4 以来您可以进行排序的方式已经改变。下面显示了一些正在为我的文档索引的字段的 sn-p。

@Override
public Document generateDocument(Process entity)
{
    Document doc = new Document();
    doc.add(new IntField(id, entity.getID(), Field.Store.YES));
    doc.add(new TextField(title, entity.getProcessName(), Field.Store.YES));
    doc.add(new IntField(organizationID, entity.getOrganizationID(), Field.Store.YES));
    doc.add(new StringField(versionDate, DateTools.dateToString(entity.getVersionDate(), DateTools.Resolution.SECOND), Field.Store.YES));
    doc.add(new LongField(entityDate, entity.getVersionDate().getTime(), Field.Store.YES)); 
    return doc;
}

我想先对相关性进行排序,这很好用。我遇到的问题是标题字段上的排序不起作用。我创建了一个排序字段,我尝试在一系列方法调用之后将其与 TopFieldCollector 一起使用。

public BaseSearchCore<Process, ProcessSearchResultScore>.SearchContainer search(String searchQuery, Filter filter, int page, int hitsPerPage) throws IOException, ParseException
    {
    SortField titleSort = new SortField(title, SortField.Type.STRING, true);
    return super.search(searchQuery, filter, page, hitsPerPage, title);
    }

去:

public SearchContainer search(String searchQuery, Filter filter, int page, int hitsPerPage, SortField... sortfields) throws IOException, ParseException 
    {
        Query query = getQuery(searchQuery);
        TopFieldCollector paginate = getCollector(sortfields);
        int startIndex = (page -1) * hitsPerPage;
        ScoreDoc[] hits = executeSearch(query, paginate, filter, startIndex, hitsPerPage);

        return collectResults(query, filter, hitsPerPage, hits, page);
  }

最后是应用排序字段的方法:

private TopFieldCollector getCollector(SortField sortfield) throws IOException
    {
        SortField[] sortFields = new SortField[] {SortField.FIELD_SCORE, sortField};
        Sort sorter = new Sort(sortFields);
        TopFieldCollector collector = TopFieldCollector.create(sorter, 25000, true, false, true);
        return collector;
    }

使用返回的收集器执行常规查询,并返回结果。但是,如果我尝试使用这个 SortField 进行排序,我会得到这个异常:

java.lang.IllegalStateException:字段“标题”的意外文档值类型 NONE(预期 = SORTED)。使用 UninvertingReader 或 index with docvalues。

我应该如何索引一个字符串字段以便能够在 Lucene 5 中按字母顺序(使用排序字段)对其进行排序?任何代码示例或 sn-ps 都会非常受欢迎。

按相关性搜索效果很好,但是当用户输入空搜索查询时,所有结果都具有相同的相关性。对于这些查询,我宁愿按结果标题进行排序,这会在这次 Lucene 迭代中引起问题。

【问题讨论】:

    标签: java string sorting lucene


    【解决方案1】:

    虽然在 Lucene 5.0 及更高版本中使用此索引进行排序:

    doc.add(new SortedDocValuesField("title", new BytesRef(term)));
    

    用于搜索:

    Sort sort = new Sort();
    sort.setSort(new SortField("title", SortField.Type.STRING));            
    TopDocs hits = searcher.search(bQuery.build(), pageSize, sort);
    

    【讨论】:

      【解决方案2】:

      注意:如果您首先尝试将其归结为最小的示例,则更容易找出错误(对于您自己和您所询问的人)。与其对您的体系结构和我无权访问或不了解的类等进行分类,我将解决此问题所重现的问题:

      Sort sort = new Sort(new SortField("title", SortField.Type.STRING));
      TopDocs docs = searcher.search(new TermQuery(new Term("title", "something")), 10, sort);
      

      title 的定义类似于:

      doc.add(new TextField("title", term, Field.Store.YES));
      

      这里对字段进行排序的最佳方法可能是采纳关于 docvalues 的建议。将 DocValues 添加到字段本质上是对其进行索引以进行排序,据我了解,它比 Lucene 4.X 中的典型排序方法更有效。将典型的TextFieldSortedDocValuesField 添加到同一个字段(名称)似乎效果很好,并且支持使用相同的字段名称进行搜索和排序:

      doc.add(new TextField("title", term, Field.Store.YES));
      doc.add(new SortedDocValuesField("title", new BytesRef(term)));
      

      【讨论】:

      • 感谢您的输入,您对 cme​​ts 关于我构建之前真正问题的方式的看法是正确的。我将答案标记为正确,因为我也得出了将 SortedDocValuesField 与我希望排序的字段一起使用以实际能够排序的结论。感谢您的帮助!
      • @femtoRgon 是否可以为“title”创建一个字段而不是两个单独的字段,即使这意味着创建一个自定义字段?
      • @BasilMusa - 出于所有意图和目的,这正是它的作用。就执行此操作的自定义字段而言,如果对其进行分析,您可能会遇到问题,否则您需要的一切都在 FieldType 中。
      猜你喜欢
      • 1970-01-01
      • 2012-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-16
      • 2015-07-23
      • 1970-01-01
      相关资源
      最近更新 更多