在Lucene 5.0中按字母顺序排序字符串字段

时间:2015-04-17 09:26:12

标签: java string sorting lucene

我在Lucene 5.0中对字符串字段进行排序时遇到问题。自Lucene 4改变以来你可以选择的方式。下面显示了我的文档索引的一些字段的片段。

@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;
}

我想首先考虑相关性,这很好。我遇到的问题是在标题字段上排序不起作用。我创建了一个sortfield,我试图在一系列方法调用后使用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:意外的docvalues为字段'title'键入NONE(expected = SORTED)。使用UninvertingReader或索引与docvalues。

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

按相关性搜索工作正常,但当用户输入空搜索查询时,所有结果都具有相同的相关性。对于那些查询,我宁愿按结果标题排序,这会导致Lucene迭代中出现问题。

2 个答案:

答案 0 :(得分:10)

注意:如果您尝试将其归结为您可以首先使用的最小示例,那么就可以更容易地找出错误(包括您自己和您要问的人)。而不是通过你的架构和课程,我无法访问或了解任何事情,等等,我将解决这个问题:

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

标题的定义如下:

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)));

答案 1 :(得分: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);