最近需求中需要使用lucene的分组查询,现有API使用GroupingSearch查询,代码如下:
GroupingSearch groupingSearch = new GroupingSearch("compId");
groupingSearch.setGroupSort(new Sort(SortField.FIELD_SCORE));
groupingSearch.setFillSortFields(true);
//groupingSearch.setCachingInMB(8.0, true);
groupingSearch.setAllGroups(true);
// groupingSearch.setAllGroupHeads(true);
groupingSearch.setGroupDocsLimit(10);
IndexWriterConfig config = new IndexWriterConfig(new IKAnalyzer());
config.setOpenMode(OpenMode.CREATE_OR_APPEND);
LogByteSizeMergePolicy mergePolicy = new LogByteSizeMergePolicy();
Directory directory = NIOFSDirectory.open(new File("/Users/lvyanglin/searchdata/search/offlineindex").toPath()); // 新建的文件在子目录
mergePolicy.setMergeFactor(5);
config.setMergePolicy(mergePolicy);
config.setSimilarity(new ClassicSimilarity());
IndexWriter indexWriter = new IndexWriter(directory, config);
IndexReader reader = DirectoryReader.open(indexWriter);
IndexSearcher isearcher = new IndexSearcher(reader);
Query query = new TermQuery(new Term("id", "20755185"));
TopGroups<BytesRef> result = groupingSearch.search(isearcher, query, 0, 1000);
System.out.println("搜索命中数:" + result.totalHitCount);
System.out.println("搜索结果分组数:" + result.groups.length);
Document document;
for (GroupDocs<BytesRef> groupDocs : result.groups) {
System.out.println("分组:" + groupDocs.groupValue.utf8ToString());
System.out.println("组内记录:" + groupDocs.totalHits);
// System.out.println("groupDocs.scoreDocs.length:" +
// groupDocs.scoreDocs.length);
for (ScoreDoc scoreDoc : groupDocs.scoreDocs) {
System.out.println("compId="+isearcher.doc(scoreDoc.doc).get("compId"));
}
}
}
但是不管怎么调试都会出现:
Exception in thread "main" java.lang.IllegalStateException: unexpected docvalues type NONE for field 'compId' (expected=SORTED). Re-index with correct docvalues type.
at org.apache.lucene.index.DocValues.checkField(DocValues.java:212)
at org.apache.lucene.index.DocValues.getSorted(DocValues.java:264)
at org.apache.lucene.search.grouping.term.TermFirstPassGroupingCollector.doSetNextReader(TermFirstPassGroupingCollector.java:91)
at org.apache.lucene.search.SimpleCollector.getLeafCollector(SimpleCollector.java:33)
at org.apache.lucene.search.MultiCollector.getLeafCollector(MultiCollector.java:121)
at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:660)
at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:473)
at org.apache.lucene.search.grouping.GroupingSearch.groupByFieldOrFunction(GroupingSearch.java:193)
at org.apache.lucene.search.grouping.GroupingSearch.search(GroupingSearch.java:129)
at com.shunteng.service.test.v3.GroupSearchTest2.main(GroupSearchTest2.java:79)
问题在于分组排序字段必须为SortedDocValuesField,因为是long类型字段所以我就使用SortedNumbericDocValuesField这个字段建索引,运行后还是发生以上错误。百度基本上找个不到问题原因,官网也是没什么解释,官网wiki上也没有例子。只能debug代码来找出问题,看是在那个环节出现的异常。直接抛出异常的方法是DocValues.java中checkField方法,
private static void checkField(LeafReader in, String field, DocValuesType... expected) {
FieldInfo fi = in.getFieldInfos().fieldInfo(field);
if (fi != null) {
DocValuesType actual = fi.getDocValuesType();
throw new IllegalStateException("unexpected docvalues type " + actual +
" for field '" + field + "' " +
(expected.length == 1
? "(expected=" + expected[0]
: "(expected one of " + Arrays.toString(expected)) + "). " +
"Re-index with correct docvalues type.");
}
}
看下面方法进入此方法抛出异常,制药进入上面这个方法必定抛出异常。所以要找出为什么进入这个方法:
public static SortedDocValues getSorted(LeafReader reader, String field) throws IOException {
SortedDocValues dv = reader.getSortedDocValues(field);
if (dv == null) {
checkField(reader, field, DocValuesType.SORTED);
return emptySorted();
} else {
return dv;
}
}
上面这个方法getSorted是关键条件,深入=reader.getSortedDocValues(field);这个方法如下
@Override
@Override
public final SortedDocValues getSortedDocValues(String field) throws IOException {
ensureOpen();
Map<String,Object> dvFields = docValuesLocal.get();
Object previous = dvFields.get(field);
if (previous != null && previous instanceof SortedDocValues) {
return (SortedDocValues) previous;
} else {
FieldInfo fi = getDVField(field, DocValuesType.SORTED);
if (fi == null) {
return null;
}
SortedDocValues dv = getDocValuesReader().getSorted(fi);
dvFields.put(field, dv);
return dv;
}
}
这个previous instanceof SortedDocValues 如果成立 或这个后面类型为SortedDocValuesField 就不会有下面return null,问题就是在于我们配置索引分组字段的时候必须要使用SortedDocValuesField 这个类型的字段。不能使用SortedNumbericDocValuesField,来建索引,这个也是lucene奇葩地方。
我写这个文章目的是总结最近起找问题的心得,在使用阿里巴巴dubbo的时候也遇到到处找不到资料的情况,我们需要一步一步的debug出来问题根源比baidu上更靠谱速度也许更快。
分享到:
相关推荐
一、Lucene分组查询原理 Lucene的分组查询(Faceting)是通过对索引中的文档进行多级分类来实现的。它首先会计算每个分面值的文档频率,然后对匹配查询条件的文档进行分组计数。这个过程涉及到倒排索引的遍历和统计...
一、Lucene分组查询 在数据检索中,分组查询常常用于对结果进行分类展示,帮助用户更清晰地理解搜索结果的分布。Lucene通过`FieldCache`和`Grouping` API来实现这一功能。首先,我们需要在索引时为需要分组的字段...
lucene-grouping-3.5.0.jar分组统计+分类统计插件 分组统计+分类统计
5. 默认实现了一套强大的查询引擎:Lucene的查询引擎默认实现了布尔操作、模糊查询(FuzzySearch)、分组查询等多种功能,用户无需编写代码即可获得强大的查询能力。 Lucene在搜索过程中,首先需要建立索引。索引...
- **调试工具**:提供工具帮助开发者调试索引和查询问题。 - **社区贡献**:参与社区活动,贡献代码或文档,促进Lucene的发展。 #### 八、Lucene的移植与集成 - **跨平台支持**:由于Lucene被移植到了多种编程语言...
4. Lucene-5127:删除了`IndexWriterConfig`中的`setTermIndexInterval`、`setReaderTermsIndexDivisor`和`TermsIndexDivisor`,以减少内存使用。术语索引间隔的配置应直接传递给编解码器,或者针对每个字段进行设置...
5. **预置的查询引擎**:Lucene默认提供了一套强大的查询引擎,包括布尔操作、模糊查询、分组查询等功能,大大减轻了开发者的负担。 #### 四、Lucene的运行机制 Lucene的核心功能主要包括两个方面:建立索引库和...
4. **查询处理**:用户提交查询请求时,Solr会解析请求中的参数,并利用已有的索引快速返回结果。 5. **结果排序与过滤**:根据用户的需求对检索结果进行排序、分组等操作。 6. **返回结果**:将最终的检索结果以...
总结,Lucene 5.2.1版本提供了完整的全文检索解决方案,包括高效的索引构建、灵活的查询语法、强大的搜索功能以及丰富的扩展特性。无论是小型应用还是大规模企业级系统,Lucene都能满足开发者对高效全文搜索的需求。...
总结来说,Lucene.net提供了一个强大且灵活的框架,用于构建高性能的全文搜索引擎。通过理解并熟练运用上述的属性和组件,开发者可以创建出满足各种需求的搜索解决方案。在实际应用中,根据具体场景选择合适的...
4. **文档和字段**: `lucene-docvalues.jar`和`lucene-grouping.jar`分别处理文档值和文档分组,这对于根据特定字段对搜索结果进行排序或分组非常有用。 5. **高性能特性**: `lucene-highlighter.jar`提供了高亮...
- **查询类型**:详细说明了Lucene支持的各种查询类型,如布尔查询(Boolean Query)、短语查询(Phrase Query)等,并探讨了如何根据用户输入创建这些查询。 - **人类可读性**:讨论了如何使查询更易于理解和编写,以及...
聚合查询(Aggregations)是ES中的统计分析工具,用于对数据进行汇总和分组,有助于我们获取更深入的洞察。 1. **术语聚合(Term Aggregation)**:按指定字段的唯一值进行分组,计算每组的数量。例如,统计某个...
Solr还提供了灵活的XML配置,支持Lucene查询语言的扩展,如结果分组、过滤和高亮显示,以及一个全面的HTML管理界面和日志监控功能。 Solr与Lucene的关系并非替代,而是互补。Lucene是一个全文检索库,专注于搜索...
Java 使用 ES 查询的示例代码 Java 是当前最流行的编程语言之一,而 Elasticsearch(简称 ES)是当前流行的企业...在 Java 中使用 ES 可以解决查询速度不够快、效率不够高的问题,使用 ES 工具类可以轻松地进行查询。
开发者可以将Lucene集成到自己的应用程序中,为文本数据建立索引。Lucene的流行在于其灵活性,可以处理各种文本格式的文档。 3. Solr与Lucene的区别 Solr是对Lucene的封装和扩展,提供了一个完整的搜索服务器解决...
- **分组查询**:对于数据的分组统计等操作,HBase同样存在局限性。 - **分词检索**:对于文本数据的检索,需要进行分词处理,这也是HBase所欠缺的能力之一。 ### 解决方案探索 为了解决上述问题,通常会采用以下...
### Apache Solr 企业搜索引擎教程知识点总结 #### 1. Apache Solr 概述 - **Solr**:Apache Solr 是一款高度可扩展且高性能的企业级搜索平台,由Apache软件基金会维护。它是一个开源搜索服务器,使用Java语言编写...
Solr 是 Lucene 的一个面向企业级搜索的封装和扩展,它提供了搜索服务器的完整功能,包括动态字段、唯一键、查询语言扩展、结果分组过滤、文本分析、缓存策略、管理界面、日志监控以及增量更新和快照发布等。...