Lucene问题之:java.lang.ArrayIndexOutOfBoundsException

FacetField的使用

在使用FacetField创建的field后,后面使用它进行统计查询的时候,总是报出如下的异常信息:

java.lang.ArrayIndexOutOfBoundsException: 2
	at org.apache.lucene.facet.taxonomy.IntTaxonomyFacets.increment(IntTaxonomyFacets.java:88)
	at org.apache.lucene.facet.taxonomy.IntTaxonomyFacets.increment(IntTaxonomyFacets.java:80)
	at org.apache.lucene.facet.taxonomy.FastTaxonomyFacetCounts.count(FastTaxonomyFacetCounts.java:88)
	at org.apache.lucene.facet.taxonomy.FastTaxonomyFacetCounts.<init>(FastTaxonomyFacetCounts.java:54)
	at org.apache.lucene.facet.taxonomy.FastTaxonomyFacetCounts.<init>(FastTaxonomyFacetCounts.java:44)

跟踪源代码发现是如下两个地方的值不一致导致的:

public abstract class IntTaxonomyFacets extends TaxonomyFacets {
  /** Per-ordinal value. */
  private final int[] values;
  private final IntIntScatterMap sparseValues;

FastTaxonomyFacetCounts类中下面代码中计算出的ord值超出了上面代码中values的长度。

for (int doc = it.nextDoc(); doc != DocIdSetIterator.NO_MORE_DOCS; doc = it.nextDoc()) {
        final BytesRef bytesRef = dv.binaryValue();
        byte[] bytes = bytesRef.bytes;
        int end = bytesRef.offset + bytesRef.length;
        int ord = 0;
        int offset = bytesRef.offset;
        int prev = 0;
        while (offset < end) {
          byte b = bytes[offset++];
          if (b >= 0) {
            prev = ord = ((ord << 7) | b) + prev;
            increment(ord);
            ord = 0;
          } else {
            ord = (ord << 7) | (b & 0x7F);
          }
        }
      }

为什么会超出呢,我们继续往下面分析。那么这个int[] values里面到底是存的是什么呢?我们继续看下面的代码:

  protected IntTaxonomyFacets(String indexFieldName, TaxonomyReader taxoReader, FacetsConfig config, FacetsCollector fc) throws IOException {
    super(indexFieldName, taxoReader, config);
    if (useHashTable(fc, taxoReader)) {
      sparseValues = new IntIntScatterMap();
      values = null;
    } else {
      sparseValues = null;
      values = new int[taxoReader.getSize()];
    }
  }

从上面的代码中我们可以看出它的值为new int[taxoReader.getSize()],是由taxoReader.getSize()决定大小的。再看TaxonomyReader中有如下的一个size

  /**
   * Returns the number of categories in the taxonomy. Note that the number of
   * categories returned is often slightly higher than the number of categories
   * inserted into the taxonomy; This is because when a category is added to the
   * taxonomy, its ancestors are also added automatically (including the root,
   * which always get ordinal 0).
   */
  public abstract int getSize();

它的实现类DirectoryTaxonomyReader中的方法:

@Override
  public int getSize() {
    ensureOpen();
    return indexReader.numDocs();
  }

到这里大家应该能够看出这个values的长度就是当前reader下的文档数决定的。继续往下跟踪代码发现:
在这里插入图片描述
TaxonomyWriter生成的上面的文件异常,只有一个segments,而正常的像下面这样有两个segments:
在这里插入图片描述
到这里才联想起来我在代码中的TaxonomyWriter可能没有提交,去检查,发现的确没有提交,加上commit之后问题解决。

后记

文中values的长度是由每个segments中的文档数之后决定的,本文中我明明只有一个文档,TaxonomyWriter为什么会有两个segment,一个segment里面的文档数是1个,还有一个里面的文档数是4个。这里就没有搞明白为什么会多出这4个出来。有知道的朋友可以指点下。

### Java中`java.lang.NoClassDefFoundError: org.apache.lucene.util.Accountable`解决方案 当遇到`java.lang.NoClassDefFoundError: org.apache.lucen‌e.util.Accountable`错误时,表明程序尝试访问Lucene库中的Accountable类却未能成功找到它。此问题通常不是因为缺少整个JAR文件,而是由于特定版本的Lucene JAR未被正确引入或兼容性问题。 对于此类问题的一个常见解决方法是在项目的构建路径中加入正确的Lucene核心库版本。具体操作可以参照如下建议: 确保使用的Lucene版本支持所需的功能组件。例如,在某些较新版本的Lucene中可能已经移除了旧版中存在的类;因此,确认所依赖的具体模块确实包含了所需的`org.apache.lucene.util.Accountable`类至关重要[^3]。 另外一种情况是Tomcat服务器在启动过程中并未加载必要的JAR包。针对这种情况,可考虑将缺失的JAR文件手动复制至Web应用程序下的`WEB-INF/lib`目录内,并重启服务来验证效果[^1]。 最后,清理并重建项目有助于消除潜在的编译缓存问题,这可以通过IDE提供的功能完成,比如Eclipse中的Project -> Clean... 和 Project -> Build All选项[^2]。 ```xml <!-- Maven pom.xml配置示例 --> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <version>8.9.0</version><!-- 请根据实际需求调整版本号 --> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-backward-codecs</artifactId> <version>8.9.0</version><!-- 确保与其他Lucene组件版本一致 --> </dependency> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值