Lucene 5排序问题(UninvertedReader和DocValues)

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

线程“main”中的exceptionjava.lang.IllegalStateException:字段’stars’的意外docvalues类型为NONE(expected = NUM​​ERIC)。 使用UninvertingReader或索引与docvalues。
在org.apache.lucene.index.DocValues.checkField(DocValues.java:208)
at org.apache.lucene.index.DocValues.getNumeric(DocValues.java:227)
at org.apache.lucene.search.FieldComparator $ NumericComparator.getNumericDocValues(FieldComparator.java:167)
at org.apache.lucene.search.FieldComparator $ NumericComparator.doSetNextReader(FieldComparator.java:153)
at org.apache.lucene.search.SimpleFieldComparator.getLeafComparator(SimpleFieldComparator.java:36)
在org.apache.lucene.search.FieldValueHitQueue.getComparators(FieldValueHitQueue.java:183)
at 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)

我索引了一个文档,其中包含一个双字段“星号”,我需要用它来对搜索结果进行排序(具有最高“星号”值的文档需要在顶部)。

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

然后我在“stars”字段上实现了带有Sort选项的Search命令,如下所示:

 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做一些事情。 但是什么?

您需要定义自定义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(); } 

并使用以下命令添加到您的doc:

 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。

为了将来参考,以下是@ 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的构造函数将复制已在存储类型上设置的所有属性。

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