1. 程式人生 > >Lucene問題之:java.lang.ArrayIndexOutOfBoundsException

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個出來。有知道的朋友可以指點下。