Java Lucene 5排序问题(UninvertedReader和DocValues)

Java Lucene 5排序问题(UninvertedReader和DocValues),java,sorting,search,lucene,Java,Sorting,Search,Lucene,我正在开发一个内置于Lucene 5.2.1的搜索引擎,但是我在搜索的排序更新选项方面遇到了问题。使用排序选项搜索时出现错误: 线程“main”java.lang.IllegalStateException中出现异常:意外的docvalues为字段“stars”键入NONE(预期为数字)。将UnvertingReader或索引与docvalues一起使用。 位于org.apache.lucene.index.DocValues.checkField(DocValues.java:208) 位于o

我正在开发一个内置于Lucene 5.2.1的搜索引擎,但是我在搜索的排序更新选项方面遇到了问题。使用排序选项搜索时出现错误:

线程“main”java.lang.IllegalStateException中出现异常:意外的docvalues为字段“stars”键入NONE(预期为数字)。将UnvertingReader或索引与docvalues一起使用。
位于org.apache.lucene.index.DocValues.checkField(DocValues.java:208)
位于org.apache.lucene.index.DocValues.getNumeric(DocValues.java:227)
在org.apache.lucene.search.FieldComparator$NumericComparator.getNumericDocValues(FieldComparator.java:167)
在org.apache.lucene.search.FieldComparator$numericparator.dosetnextrader(FieldComparator.java:153)
在org.apache.lucene.search.SimpleFeldComparator.getLeafComparator(SimpleFeldComparator.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.indexsearch.search(indexsearch.java:762)
在org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:485)上
位于org.apache.lucene.search.indexsearch.search(indexsearch.java:694)
在org.apache.lucene.search.IndexSearcher.searchAfter(IndexSearcher.java:679)
在org.apache.lucene.search.IndexSearcher.searchAfter(IndexSearcher.java:621)
位于org.apache.lucene.search.indexsearch.search(indexsearch.java:527)
位于org.apache.lucene.search.indexsearch.search(indexsearch.java:577)
位于SearchEngine.searchBusinessByCategory(SearchEngine.java:145)
at Tests.searchEngineTest(Tests.java:137)
Main.Main(Main.java:13)

我为一个文档编制了索引,该文档包含一个双字段“stars”,我需要使用该字段对搜索结果进行排序(具有最高“stars”值的文档需要位于顶部)

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

SortField sortfield = new SortField("stars", SortField.Type.DOUBLE, true);
Sort sort = new Sort(sortfield);
mySearcher.search(query, maxdocs, sort);
我在网上找到了类似的讨论,但他们都在谈论SolR(有时是弹性搜索),但他们既没有提供Lucene片段,也没有为Lucene 5提供更通用的实现解决方案策略。例如:

Solr使用DocValues并使用UnvertingReader包装, 如果用户没有为它们编制索引(启动性能为负,并且 记忆效应)。但一般来说,您应该真正启用DocValues 用于要排序的字段。 (从h起)


我发现我必须对UnvertingReader或DocValues进行一些处理。但是什么呢?

您需要定义一个自定义的
字段类型,因为您使用的双字段构造函数不存储docvalue

例:

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

Document doc = new Document();
doc.add(new DoubleField("stars", stars, DOUBLE_FIELD_TYPE_STORED_SORTED));
当你使用

new DoubleField("stars", stars, Stored.YES);
您实际上正在使用此
字段类型

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()解决了问题。

如何从文档的字段中获取值?对于数字类型,它应该与
doc.getField(“stars”).numericValue().doubleValue()一起使用使用这个新的字段类型似乎有效,但现在我无法再打印双精度值。稍后在我的应用程序中,我想显示双“星”字段,但当我调用doc.getValues(“星”)时,我得到了我猜的堆位置([Ljava.lang.String;@799d4f69),我无法返回原始的双值。我还尝试了doc.getField(“星”)和doc.getField(“星”).numericValue().doubleValue();但我得到的只是一个空指针异常。如果存储了字段类型,为什么会发生这种情况?
Document.getValues()
返回一个字符串数组,因此需要遍历它。is
doc.getField(“stars”)
返回
null
doc.getField(“stars”).numericValue()
?糟糕,在重新索引
doc.getField(“stars”).numericValue()
后效果很好。当然。非常感谢您的支持!@user1071777我在上遇到了另一个类似的答案,但建议创建两个单独的字段。您的解决方案会给出相同的结果吗?
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();
}
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();
}