Index: contrib/queries/src/java/org/apache/lucene/search/trie/AbstractTrieRangeFilter.java =================================================================== --- contrib/queries/src/java/org/apache/lucene/search/trie/AbstractTrieRangeFilter.java (revision 746790) +++ contrib/queries/src/java/org/apache/lucene/search/trie/AbstractTrieRangeFilter.java (working copy) @@ -33,11 +33,11 @@ abstract class AbstractTrieRangeFilter extends Filter { - AbstractTrieRangeFilter(final String[] fields, final int precisionStep, + AbstractTrieRangeFilter(final String[] fields, final int[] precisionSteps, Number min, Number max, final boolean minInclusive, final boolean maxInclusive ) { this.fields=(String[])fields.clone(); - this.precisionStep=precisionStep; + this.precisionSteps=(int[])precisionSteps.clone(); this.min=min; this.max=max; this.minInclusive=minInclusive; @@ -66,12 +66,12 @@ if (this.getClass().equals(o.getClass())) { AbstractTrieRangeFilter q=(AbstractTrieRangeFilter)o; return ( - Arrays.equals(fields,q.fields) && (q.min == null ? min == null : q.min.equals(min)) && (q.max == null ? max == null : q.max.equals(max)) && minInclusive==q.minInclusive && maxInclusive==q.maxInclusive && - precisionStep==q.precisionStep + Arrays.equals(fields,q.fields) && + Arrays.equals(precisionSteps,q.precisionSteps) ); } return false; @@ -79,7 +79,8 @@ //@Override public final int hashCode() { - int hash=Arrays.asList(fields).hashCode()+(precisionStep^0x64365465); + int hash = Arrays.asList(fields).hashCode(); + for (int i=0; iThis is the counterpart to {@link TrieUtils#addIndexedFields(Document,String[],String[])}. */ - public IntTrieRangeFilter(final String[] fields, final int precisionStep, + public IntTrieRangeFilter(final String[] fields, final int[] precisionSteps, Integer min, Integer max, final boolean minInclusive, final boolean maxInclusive ) { - super(fields, precisionStep, min, max, minInclusive, maxInclusive); + super(fields, precisionSteps, min, max, minInclusive, maxInclusive); } /** @@ -126,7 +126,7 @@ } } - }, precisionStep, minBound, maxBound); + }, precisionSteps, minBound, maxBound); } catch (RuntimeException e) { if (e.getCause() instanceof IOException) throw (IOException)e.getCause(); throw e; Index: contrib/queries/src/java/org/apache/lucene/search/trie/LongTrieRangeFilter.java =================================================================== --- contrib/queries/src/java/org/apache/lucene/search/trie/LongTrieRangeFilter.java (revision 746790) +++ contrib/queries/src/java/org/apache/lucene/search/trie/LongTrieRangeFilter.java (working copy) @@ -51,7 +51,7 @@ ) { this( new String[]{field, field+TrieUtils.LOWER_PRECISION_FIELD_NAME_SUFFIX}, - precisionStep,min,max,minInclusive,maxInclusive + new int[]{precisionStep},min,max,minInclusive,maxInclusive ); } @@ -68,7 +68,7 @@ public LongTrieRangeFilter(final String field, final String lowerPrecisionField, final int precisionStep, final Long min, final Long max, final boolean minInclusive, final boolean maxInclusive ) { - this(new String[]{field, lowerPrecisionField},precisionStep,min,max,minInclusive,maxInclusive); + this(new String[]{field, lowerPrecisionField},new int[]{precisionStep},min,max,minInclusive,maxInclusive); } /** @@ -82,10 +82,10 @@ * To query double values use the converter {@link TrieUtils#doubleToSortableLong}. *

This is the counterpart to {@link TrieUtils#addIndexedFields(Document,String[],String[])}. */ - public LongTrieRangeFilter(final String[] fields, final int precisionStep, + public LongTrieRangeFilter(final String[] fields, final int[] precisionSteps, Long min, Long max, final boolean minInclusive, final boolean maxInclusive ) { - super(fields, precisionStep, min, max, minInclusive, maxInclusive); + super(fields, precisionSteps, min, max, minInclusive, maxInclusive); } /** @@ -126,7 +126,7 @@ } } - }, precisionStep, minBound, maxBound); + }, precisionSteps, minBound, maxBound); } catch (RuntimeException e) { if (e.getCause() instanceof IOException) throw (IOException)e.getCause(); throw e; Index: contrib/queries/src/java/org/apache/lucene/search/trie/TrieUtils.java =================================================================== --- contrib/queries/src/java/org/apache/lucene/search/trie/TrieUtils.java (revision 746792) +++ contrib/queries/src/java/org/apache/lucene/search/trie/TrieUtils.java (working copy) @@ -294,17 +294,40 @@ *

To achieve this, use {@link #addIndexedFields(Document,String,String[])}. */ public static String[] trieCodeLong(long val, int precisionStep) { + // this is a optimized version for a equidistant precisionStep if (precisionStep<1 || precisionStep>64) throw new IllegalArgumentException("precisionStep may only be 1..64"); String[] arr = new String[63/precisionStep+1]; - int idx = 0; - for (int shift=0; shift<64; shift+=precisionStep) { + for (int idx=0,shift=0; shift<64; shift+=precisionStep) { arr[idx++] = longToPrefixCoded(val, shift); } return arr; } /** + * **TODO** Expert: Returns a sequence of trie coded numbers suitable for {@link LongTrieRangeFilter}. + * Each successive string in the list has had it's precision reduced by precisionStep. + * For sorting, index the first full-precision value into a separate field and the + * remaining values into another field. + *

To achieve this, use {@link #addIndexedFields(Document,String,String[])}. + */ + public static String[] trieCodeLong(long val, int[] precisionSteps) { + // determine size of trie array + int size=0; + for (int shift=0; shift<64; ) { + shift += precisionSteps[Math.min(precisionSteps.length-1, size)]; + size++; + } + // create trie entries + final String[] arr = new String[size]; + for (int idx=0,shift=0; idxprecisionStep. * For sorting, index the first full-precision value into a separate field and the @@ -312,17 +335,40 @@ *

To achieve this, use {@link #addIndexedFields(Document,String,String[])}. */ public static String[] trieCodeInt(int val, int precisionStep) { + // this is a optimized version for a equidistant precisionStep if (precisionStep<1 || precisionStep>32) throw new IllegalArgumentException("precisionStep may only be 1..32"); String[] arr = new String[31/precisionStep+1]; - int idx = 0; - for (int shift=0; shift<32; shift+=precisionStep) { + for (int idx=0,shift=0; shift<32; shift+=precisionStep) { arr[idx++] = intToPrefixCoded(val, shift); } return arr; } /** + * **TODO** Expert: Returns a sequence of trie coded numbers suitable for {@link IntTrieRangeFilter}. + * Each successive string in the list has had it's precision reduced by precisionStep. + * For sorting, index the first full-precision value into a separate field and the + * remaining values into another field. + *

To achieve this, use {@link #addIndexedFields(Document,String,String[])}. + */ + public static String[] trieCodeInt(int val, int[] precisionSteps) { + // determine size of trie array + int size=0; + for (int shift=0; shift<32; ) { + shift += precisionSteps[Math.min(precisionSteps.length-1, size)]; + size++; + } + // create trie entries + final String[] arr = new String[size]; + for (int idx=0,shift=0; idxfield+LOWER_PRECISION_FIELD_NAME_SUFFIX. *

This is the recommended variant to add trie fields to the index. @@ -395,10 +441,24 @@ ) { if (precisionStep<1 || precisionStep>64) throw new IllegalArgumentException("precisionStep may only be 1..64"); - splitRange(builder, 64, precisionStep, minBound, maxBound); + splitRange(builder, 64, new int[]{precisionStep}, minBound, maxBound); } /** + * **TODO** Expert: Splits a long range recursively. + * You may implement a builder that adds clauses to a + * {@link org.apache.lucene.search.BooleanQuery} for each call to its + * {@link LongRangeBuilder#addRange(String,String,int)} + * method. + *

This method is used by {@link LongTrieRangeFilter}. + */ + public static void splitLongRange(final LongRangeBuilder builder, + final int[] precisionSteps, final long minBound, final long maxBound + ) { + splitRange(builder, 64, precisionSteps, minBound, maxBound); + } + + /** * Expert: Splits an int range recursively. * You may implement a builder that adds clauses to a * {@link org.apache.lucene.search.BooleanQuery} for each call to its @@ -411,15 +471,31 @@ ) { if (precisionStep<1 || precisionStep>32) throw new IllegalArgumentException("precisionStep may only be 1..32"); - splitRange(builder, 32, precisionStep, (long)minBound, (long)maxBound); + splitRange(builder, 32, new int[]{precisionStep}, (long)minBound, (long)maxBound); } + /** + * **TODO** Expert: Splits an int range recursively. + * You may implement a builder that adds clauses to a + * {@link org.apache.lucene.search.BooleanQuery} for each call to its + * {@link IntRangeBuilder#addRange(String,String,int)} + * method. + *

This method is used by {@link IntTrieRangeFilter}. + */ + public static void splitIntRange(final IntRangeBuilder builder, + final int[] precisionSteps, final int minBound, final int maxBound + ) { + splitRange(builder, 32, precisionSteps, (long)minBound, (long)maxBound); + } + /** This helper does the splitting for both 32 and 64 bit. */ private static void splitRange( final Object builder, final int valSize, - final int precisionStep, long minBound, long maxBound + final int[] precisionSteps, long minBound, long maxBound ) { for (int level=0,shift=0;; level++) { + final int precisionStep = precisionSteps[Math.min(precisionSteps.length-1, level)]; + // calculate new bounds for inner precision final long diff = 1L << (shift+precisionStep), mask = ((1L<