Lucene 5排序问题(UninvertedReader和DocValues)

时间:2015-07-16 10:01:27

标签: java sorting search lucene

我正在使用Lucene 5.2.1构建的搜索引擎,但我在搜索的排序更新选项方面遇到了问题。使用Sort选项搜索时出错:

  

线程中的异常" main" java.lang.IllegalStateException:意外的docvalues类型为NONE for field' stars' (预期= NUM​​ERIC)。使用UninvertingReader或索引与docvalues       在org.apache.lucene.index.DocValues.checkField(DocValues.java:208)
      在org.apache.lucene.index.DocValues.getNumeric(DocValues.java:227)
      at org.apache.lucene.search.FieldComparator $ NumericComparator.getNumericDocValues(FieldComparator.java:167)
      在org.apache.lucene.search.FieldComparator $ NumericComparator.doSetNextReader(FieldComparator.java:153)
      在org.apache.lucene.search.SimpleFieldComparator.getLeafComparator(SimpleFieldComparator.java:36)
      在org.apache.lucene.search.FieldValueHitQueue.getComparators(FieldValueHitQueue.java:183)
      在org.apache.lucene.search.TopFieldCollector $ NonScoringCollector.getLeafCollector(TopFieldCollector.java:141)
      在org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:762)
      在org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:485)
      在org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:694)
      在org.apache.lucene.search.IndexSearcher.searchAfter(IndexSearcher.java:679)
      在org.apache.lucene.search.IndexSearcher.searchAfter(IndexSearcher.java:621)
      在org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:527)
      在org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:577)
      在SearchEngine.searchBusinessByCategory(SearchEngine.java:145)
      在Tests.searchEngineTest(Tests.java:137)
      在Main.main(Main.java:13)

我已经索引了一个包含双字段的文档" stars"我需要用来对搜索结果进行排序(具有最高"星级"值的文档需要排在最前面)。

Document doc = new Document();
doc.add(new DoubleField("stars", stars, Store.YES));

然后我实现了一个带有排序选项的搜索命令" stars"字段如下:

SortField sortfield = new SortField("stars", SortField.Type.DOUBLE, true);
Sort sort = new Sort(sortfield);
mySearcher.search(query, maxdocs, sort);

我在网上发现了类似的讨论,但他们都讨论过SolR(或者有时是弹性搜索),但他们既没有为Lucene 5提供Lucene片段也没有提供更通用的实施解决方案策略。例如:

  

Solr使用DocValues并使用UninvertingReader回退到包装,   如果用户没有索引它们(负启动性能和   记忆效应)。但总的来说,你应该真正启用DocValues   对于要排序的字段。   (来自h ttp://grokbase.com/t/lucene/java-user/152q2jcgzz/lucene-4-x-5-illegalstateexception-while-sorting

我发现我必须使用UninvertingReader或DocValues做一些事情。但是什么?

3 个答案:

答案 0 :(得分:5)

您需要定义自定义FieldType,因为您使用的DoubleField构造函数不存储docvalues。

例如:

private static final FieldType DOUBLE_FIELD_TYPE_STORED_SORTED = new FieldType();
static {
    DOUBLE_FIELD_TYPE_STORED_SORTED.setTokenized(true);
    DOUBLE_FIELD_TYPE_STORED_SORTED.setOmitNorms(true);
    DOUBLE_FIELD_TYPE_STORED_SORTED.setIndexOptions(IndexOptions.DOCS);
    DOUBLE_FIELD_TYPE_STORED_SORTED
        .setNumericType(FieldType.NumericType.DOUBLE);
    DOUBLE_FIELD_TYPE_STORED_SORTED.setStored(true);
    DOUBLE_FIELD_TYPE_STORED_SORTED.setDocValuesType(DocValuesType.NUMERIC);
    DOUBLE_FIELD_TYPE_STORED_SORTED.freeze();
}

使用以下内容添加到您的文档中:

Document doc = new Document();
doc.add(new DoubleField("stars", stars, DOUBLE_FIELD_TYPE_STORED_SORTED));

使用时

new DoubleField("stars", stars, Stored.YES);

您实际上正在使用此FieldType

public static final FieldType TYPE_STORED = new FieldType();
static {
    TYPE_STORED.setTokenized(true);
    TYPE_STORED.setOmitNorms(true);
    TYPE_STORED.setIndexOptions(IndexOptions.DOCS);
    TYPE_STORED.setNumericType(FieldType.NumericType.DOUBLE);
    TYPE_STORED.setStored(true);
    TYPE_STORED.freeze();
}

没有DocValues。

答案 1 :(得分:3)

以下是@ user1071777给出答案的快捷方式:

以供将来参考
private static final FieldType DOUBLE_FIELD_TYPE_STORED_SORTED = new FieldType(LongField.TYPE_STORED);

static {
    DOUBLE_FIELD_TYPE_STORED_SORTED.setDocValuesType(DocValuesType.NUMERIC);
    DOUBLE_FIELD_TYPE_STORED_SORTED.freeze();
}

接收fieldType的构造函数将复制已在存储类型上设置的所有属性。

答案 2 :(得分:0)

我使用的是DoubleField,但最后通过使用DoubleDocValuesField()来解决问题。