From 8957786bf788f1aa86c33495f266f124d0b0617f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Tue, 7 Apr 2020 16:22:46 +0200 Subject: [PATCH] HSEARCH-1929 Work on raw, long values for Lucene float/double aggregations It's less code, and we don't need more at the moment. We can always revert this commit if one day we need more. --- .../docvalues/impl/DoubleMultiValues.java | 90 --------- .../impl/DoubleMultiValuesSource.java | 41 ---- .../impl/JoiningDoubleMultiValuesSource.java | 183 ------------------ .../DoubleMultiValueRangeFacetCounts.java | 109 ----------- .../lowlevel/facet/impl/FacetCountsUtils.java | 57 +++--- .../lowlevel/impl/LuceneDoubleDomain.java | 26 +-- .../lowlevel/impl/LuceneFloatDomain.java | 16 +- .../lowlevel/impl/LuceneIntegerDomain.java | 3 +- .../types/lowlevel/impl/LuceneLongDomain.java | 3 +- 9 files changed, 56 insertions(+), 472 deletions(-) delete mode 100644 backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/docvalues/impl/DoubleMultiValues.java delete mode 100644 backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/docvalues/impl/DoubleMultiValuesSource.java delete mode 100644 backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/docvalues/impl/JoiningDoubleMultiValuesSource.java delete mode 100644 backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/facet/impl/DoubleMultiValueRangeFacetCounts.java diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/docvalues/impl/DoubleMultiValues.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/docvalues/impl/DoubleMultiValues.java deleted file mode 100644 index 3835d258c98..00000000000 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/docvalues/impl/DoubleMultiValues.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Hibernate Search, full-text search for your domain model - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.search.backend.lucene.lowlevel.docvalues.impl; - -import java.io.IOException; - -/** - * A per-document, unordered sequence of double values. - */ -public abstract class DoubleMultiValues { - - protected DoubleMultiValues() { - } - - /** - * Advance this instance to the given document id - * - * @return true if there is a value for this document - */ - public abstract boolean advanceExact(int doc) throws IOException; - - /** - * @return true if there is a next value for this document, - * i.e. if nextValue() can be called. - */ - public abstract boolean hasNextValue() throws IOException; - - /** - * @return The next value for the current document. - * Can only be called after {@link #hasNextValue()} returned {@code true}. - */ - public abstract double nextValue() throws IOException; - - public static DoubleMultiValues fromDocValues(SortedNumericDoubleDocValues docValues) { - return new DocValuesDoubleMultiValues( docValues ); - } - - /** - * An empty DoubleMultiValues instance that always returns {@code false} from {@link #advanceExact(int)} - */ - public static final DoubleMultiValues EMPTY = new DoubleMultiValues() { - @Override - public boolean advanceExact(int doc) { - return false; - } - - @Override - public boolean hasNextValue() { - throw new UnsupportedOperationException(); - } - - @Override - public double nextValue() { - throw new UnsupportedOperationException(); - } - }; - - - private static class DocValuesDoubleMultiValues extends DoubleMultiValues { - - private final SortedNumericDoubleDocValues values; - private int remaining; - - DocValuesDoubleMultiValues(SortedNumericDoubleDocValues values) { - this.values = values; - } - - @Override - public boolean advanceExact(int doc) throws IOException { - boolean found = values.advanceExact( doc ); - this.remaining = found ? values.docValueCount() : 0; - return found; - } - - @Override - public boolean hasNextValue() { - return remaining > 0; - } - - @Override - public double nextValue() throws IOException { - --remaining; - return values.nextValue(); - } - } -} diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/docvalues/impl/DoubleMultiValuesSource.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/docvalues/impl/DoubleMultiValuesSource.java deleted file mode 100644 index eed566ee0de..00000000000 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/docvalues/impl/DoubleMultiValuesSource.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Hibernate Search, full-text search for your domain model - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or . - */ - -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.hibernate.search.backend.lucene.lowlevel.docvalues.impl; - -import java.io.IOException; - -import org.apache.lucene.index.LeafReaderContext; - -/** - * A source of {@link DoubleMultiValues}. - */ -public abstract class DoubleMultiValuesSource { - - /** - * @return a {@link DoubleMultiValues} instance for the passed-in LeafReaderContext. - */ - public abstract DoubleMultiValues getValues(LeafReaderContext ctx) throws IOException; - -} diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/docvalues/impl/JoiningDoubleMultiValuesSource.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/docvalues/impl/JoiningDoubleMultiValuesSource.java deleted file mode 100644 index 99badeb6d1c..00000000000 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/docvalues/impl/JoiningDoubleMultiValuesSource.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Hibernate Search, full-text search for your domain model - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.search.backend.lucene.lowlevel.docvalues.impl; - -import java.io.IOException; -import java.util.Objects; -import java.util.function.Function; - -import org.hibernate.search.backend.lucene.lowlevel.join.impl.JoinChildrenIdIterator; -import org.hibernate.search.backend.lucene.lowlevel.join.impl.NestedDocsProvider; - -import org.apache.lucene.index.DocValues; -import org.apache.lucene.index.LeafReaderContext; -import org.apache.lucene.index.SortedNumericDocValues; -import org.apache.lucene.search.DocIdSetIterator; -import org.apache.lucene.util.BitSet; - -/** - * A source of {@link DoubleMultiValues} that automatically fetches values from nested documents if necessary. - */ -public abstract class JoiningDoubleMultiValuesSource extends DoubleMultiValuesSource { - - /** - * Creates a {@link JoiningDoubleMultiValuesSource} that wraps a double-valued field - * - * @param field the field - * @param nested the nested provider - * @return A {@link JoiningDoubleMultiValuesSource} - */ - public static JoiningDoubleMultiValuesSource fromDoubleField(String field, NestedDocsProvider nested) { - return fromField( field, nested, SortedNumericDoubleDocValues::fromDoubleField ); - } - - /** - * Creates a {@link JoiningDoubleMultiValuesSource} that wraps a float-valued field - * - * @param field the field - * @param nested the nested provider - * @return A {@link JoiningDoubleMultiValuesSource} - */ - public static JoiningDoubleMultiValuesSource fromFloatField(String field, NestedDocsProvider nested) { - return fromField( field, nested, SortedNumericDoubleDocValues::fromFloatField ); - } - - private static JoiningDoubleMultiValuesSource fromField(String field, NestedDocsProvider nested, - Function decoder) { - return new FieldDoubleMultiValuesSource( field, nested, decoder ); - } - - protected final NestedDocsProvider nestedDocsProvider; - - public JoiningDoubleMultiValuesSource(NestedDocsProvider nestedDocsProvider) { - this.nestedDocsProvider = nestedDocsProvider; - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - JoiningDoubleMultiValuesSource that = (JoiningDoubleMultiValuesSource) o; - return Objects.equals( nestedDocsProvider, that.nestedDocsProvider ); - } - - @Override - public int hashCode() { - return nestedDocsProvider.hashCode(); - } - - @Override - public DoubleMultiValues getValues(LeafReaderContext ctx) throws IOException { - SortedNumericDoubleDocValues values = getSortedNumericDoubleDocValues( ctx ); - - if ( nestedDocsProvider == null ) { - return DoubleMultiValues.fromDocValues( values ); - } - - final BitSet rootDocs = nestedDocsProvider.parentDocs( ctx ); - final DocIdSetIterator innerDocs = nestedDocsProvider.childDocs( ctx ); - return join( values, rootDocs, innerDocs ); - } - - protected abstract SortedNumericDoubleDocValues getSortedNumericDoubleDocValues(LeafReaderContext ctx) throws IOException; - - protected DoubleMultiValues join(SortedNumericDoubleDocValues values, final BitSet parentDocs, - final DocIdSetIterator childDocs) { - if ( parentDocs == null || childDocs == null ) { - return DoubleMultiValues.EMPTY; - } - - JoinChildrenIdIterator joinIterator = new JoinChildrenIdIterator( parentDocs, childDocs, values ); - - return new DoubleMultiValues() { - int currentParentDoc = -1; - int remainingValuesForChild = 0; - - @Override - public boolean advanceExact(int parentDoc) throws IOException { - assert parentDoc >= currentParentDoc : "can only evaluate current and upcoming parent docs"; - if ( parentDoc == currentParentDoc ) { - return hasNextValue(); - } - - currentParentDoc = parentDoc; - remainingValuesForChild = 0; // To be set in the next call to hasNextValue() - - return joinIterator.advanceExact( parentDoc ); - } - - @Override - public boolean hasNextValue() throws IOException { - if ( remainingValuesForChild > 0 ) { - return true; - } - - if ( joinIterator.advanceValuesToNextChild() ) { - remainingValuesForChild = values.docValueCount(); - return true; - } - else { - remainingValuesForChild = 0; - return false; - } - } - - @Override - public double nextValue() throws IOException { - --remainingValuesForChild; - return values.nextValue(); - } - }; - } - - private static class FieldDoubleMultiValuesSource extends JoiningDoubleMultiValuesSource { - - private final String field; - private final Function decoder; - - public FieldDoubleMultiValuesSource(String field, NestedDocsProvider nestedDocsProvider, - Function decoder) { - super( nestedDocsProvider ); - this.field = field; - this.decoder = decoder; - } - - @Override - public String toString() { - return "double(" + field + "," + nestedDocsProvider + ")"; - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( !super.equals( o ) ) { - return false; - } - FieldDoubleMultiValuesSource that = (FieldDoubleMultiValuesSource) o; - return Objects.equals( field, that.field ) - && Objects.equals( decoder, that.decoder ); - } - - @Override - public int hashCode() { - return Objects.hash( super.hashCode(), field, decoder ); - } - - @Override - protected SortedNumericDoubleDocValues getSortedNumericDoubleDocValues(LeafReaderContext ctx) throws IOException { - // Numeric doc values are longs, but we want doubles - return decoder.apply( DocValues.getSortedNumeric( ctx.reader(), field ) ); - } - } - -} diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/facet/impl/DoubleMultiValueRangeFacetCounts.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/facet/impl/DoubleMultiValueRangeFacetCounts.java deleted file mode 100644 index 54a05c12cd5..00000000000 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/facet/impl/DoubleMultiValueRangeFacetCounts.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Hibernate Search, full-text search for your domain model - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.search.backend.lucene.lowlevel.facet.impl; - -import java.io.IOException; -import java.util.List; - -import org.hibernate.search.backend.lucene.lowlevel.docvalues.impl.DoubleMultiValues; -import org.hibernate.search.backend.lucene.lowlevel.docvalues.impl.DoubleMultiValuesSource; - -import org.apache.lucene.facet.FacetsCollector; -import org.apache.lucene.facet.FacetsCollector.MatchingDocs; -import org.apache.lucene.facet.range.DoubleRange; -import org.apache.lucene.facet.range.LongRange; -import org.apache.lucene.index.IndexReaderContext; -import org.apache.lucene.index.ReaderUtil; -import org.apache.lucene.search.DocIdSetIterator; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.ScoreMode; -import org.apache.lucene.search.Scorer; -import org.apache.lucene.search.Weight; -import org.apache.lucene.util.NumericUtils; - -/** - *

- * Copied with some changes from {@code org.apache.lucene.facet.range.DoubleRangeFacetCounts} - * of Apache Lucene project. - */ -public class DoubleMultiValueRangeFacetCounts extends MultiValueRangeFacetCounts { - - public DoubleMultiValueRangeFacetCounts(String field, DoubleMultiValuesSource valueSource, FacetsCollector hits, DoubleRange... ranges) throws IOException { - this( field, valueSource, hits, null, ranges ); - } - - public DoubleMultiValueRangeFacetCounts(String field, DoubleMultiValuesSource valueSource, FacetsCollector hits, Query fastMatchQuery, DoubleRange... ranges) throws IOException { - super( field, ranges, fastMatchQuery ); - count( valueSource, hits.getMatchingDocs() ); - } - - private void count(DoubleMultiValuesSource valueSource, List matchingDocs) throws IOException { - DoubleRange[] doubleRanges = (DoubleRange[]) this.ranges; - - LongRange[] longRanges = new LongRange[doubleRanges.length]; - for ( int i = 0; i < doubleRanges.length; i++ ) { - DoubleRange range = doubleRanges[i]; - longRanges[i] = new LongRange( range.label, - NumericUtils.doubleToSortableLong( range.min ), true, - NumericUtils.doubleToSortableLong( range.max ), true ); - } - - LongMultiValueRangeCounter counter = new LongMultiValueRangeCounter( longRanges ); - - int missingCount = 0; - for ( MatchingDocs hits : matchingDocs ) { - DoubleMultiValues fv = valueSource.getValues( hits.context ); - - final DocIdSetIterator fastMatchDocs; - if ( fastMatchQuery != null ) { - final IndexReaderContext topLevelContext = ReaderUtil.getTopLevelContext( hits.context ); - final IndexSearcher searcher = new IndexSearcher( topLevelContext ); - searcher.setQueryCache( null ); - final Weight fastMatchWeight = searcher.createWeight( searcher.rewrite( fastMatchQuery ), ScoreMode.COMPLETE_NO_SCORES, 1 ); - Scorer s = fastMatchWeight.scorer( hits.context ); - if ( s == null ) { - continue; - } - fastMatchDocs = s.iterator(); - } - else { - fastMatchDocs = null; - } - - DocIdSetIterator docs = hits.bits.iterator(); - - for ( int doc = docs.nextDoc(); doc != DocIdSetIterator.NO_MORE_DOCS; ) { - if ( fastMatchDocs != null ) { - int fastMatchDoc = fastMatchDocs.docID(); - if ( fastMatchDoc < doc ) { - fastMatchDoc = fastMatchDocs.advance( doc ); - } - - if ( doc != fastMatchDoc ) { - doc = docs.advance( fastMatchDoc ); - continue; - } - } - if ( fv.advanceExact( doc ) ) { - while ( fv.hasNextValue() ) { - ++totCount; - counter.add( NumericUtils.doubleToSortableLong( fv.nextValue() ) ); - } - } - else { - missingCount++; - } - - doc = docs.nextDoc(); - } - } - - missingCount += counter.fillCounts( counts ); - totCount -= missingCount; - } -} diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/facet/impl/FacetCountsUtils.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/facet/impl/FacetCountsUtils.java index c045a3e7117..9fa1bc8bffe 100644 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/facet/impl/FacetCountsUtils.java +++ b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/lowlevel/facet/impl/FacetCountsUtils.java @@ -7,11 +7,11 @@ package org.hibernate.search.backend.lucene.lowlevel.facet.impl; import java.util.Collection; +import java.util.function.ToLongFunction; import org.hibernate.search.util.common.data.Range; import org.hibernate.search.util.common.data.RangeBoundInclusion; -import org.apache.lucene.facet.range.DoubleRange; import org.apache.lucene.facet.range.LongRange; public class FacetCountsUtils { @@ -19,44 +19,39 @@ public class FacetCountsUtils { private FacetCountsUtils() { } - public static LongRange[] createLongRanges(Collection> ranges) { - LongRange[] longRanges = new LongRange[ranges.size()]; - int i = 0; - for ( Range range : ranges ) { - Number lowerBoundValue = range.getLowerBoundValue().orElse( null ); - Number upperBoundValue = range.getUpperBoundValue().orElse( null ); - longRanges[i] = new LongRange( - String.valueOf( i ), - lowerBoundValue == null ? Long.MIN_VALUE : lowerBoundValue.longValue(), - // null means -Infinity: if -Infinity is the lower bound, included or not, then Long.MIN_VALUE is included. - lowerBoundValue == null - || RangeBoundInclusion.INCLUDED.equals( range.getLowerBoundInclusion() ), - upperBoundValue == null ? Long.MAX_VALUE : upperBoundValue.longValue(), - // null means +Infinity: if +Infinity is the lower bound, included or not, then Long.MAX_VALUE is included. - upperBoundValue == null - || RangeBoundInclusion.INCLUDED.equals( range.getUpperBoundInclusion() ) - ); - ++i; - } - return longRanges; + public static LongRange[] createLongRangesForIntegralValues(Collection> ranges) { + return createLongRanges( ranges, Number::longValue, Long.MIN_VALUE, Long.MAX_VALUE, false ); + } + + public static LongRange[] createLongRangesForFloatingPointValues(Collection> ranges, + ToLongFunction encoder, T negativeInfinity, T positiveInfinity) { + return createLongRanges( ranges, encoder, negativeInfinity, positiveInfinity, true ); } - public static DoubleRange[] createDoubleRanges(Collection> ranges) { - DoubleRange[] doubleRanges = new DoubleRange[ranges.size()]; + private static LongRange[] createLongRanges(Collection> ranges, + ToLongFunction encoder, + T lowestPossibleValue, T highestPossibleValue, boolean extremaAreInfinity) { + LongRange[] longRanges = new LongRange[ranges.size()]; int i = 0; - for ( Range range : ranges ) { - Number lowerBoundValue = range.getLowerBoundValue().orElse( null ); - Number upperBoundValue = range.getUpperBoundValue().orElse( null ); - doubleRanges[i] = new DoubleRange( + for ( Range range : ranges ) { + T lowerBoundValue = range.getLowerBoundValue().orElse( null ); + T upperBoundValue = range.getUpperBoundValue().orElse( null ); + longRanges[i] = new LongRange( String.valueOf( i ), - lowerBoundValue == null ? Double.NEGATIVE_INFINITY : lowerBoundValue.doubleValue(), - RangeBoundInclusion.INCLUDED.equals( range.getLowerBoundInclusion() ), - upperBoundValue == null ? Double.POSITIVE_INFINITY : upperBoundValue.doubleValue(), + encoder.applyAsLong( lowerBoundValue == null ? lowestPossibleValue : lowerBoundValue ), + // The lower bound is included if it is explicitly included + RangeBoundInclusion.INCLUDED.equals( range.getLowerBoundInclusion() ) + // ... or if it is infinity but infinity cannot be represented + || !extremaAreInfinity && lowerBoundValue == null, + encoder.applyAsLong( upperBoundValue == null ? highestPossibleValue : upperBoundValue ), + // The upper bound is included if it is explicitly included RangeBoundInclusion.INCLUDED.equals( range.getUpperBoundInclusion() ) + // ... or if it is infinity but infinity cannot be represented + || !extremaAreInfinity && upperBoundValue == null ); ++i; } - return doubleRanges; + return longRanges; } } diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/lowlevel/impl/LuceneDoubleDomain.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/lowlevel/impl/LuceneDoubleDomain.java index 53b57ae3bc0..cd29e649f50 100644 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/lowlevel/impl/LuceneDoubleDomain.java +++ b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/lowlevel/impl/LuceneDoubleDomain.java @@ -10,9 +10,12 @@ import java.util.Collection; import java.util.Comparator; -import org.hibernate.search.backend.lucene.lowlevel.docvalues.impl.JoiningDoubleMultiValuesSource; +import org.hibernate.search.backend.lucene.lowlevel.docvalues.impl.DoubleMultiValuesToSingleValuesSource; import org.hibernate.search.backend.lucene.lowlevel.docvalues.impl.JoiningLongMultiValuesSource; +import org.hibernate.search.backend.lucene.lowlevel.docvalues.impl.MultiValueMode; import org.hibernate.search.backend.lucene.lowlevel.facet.impl.FacetCountsUtils; +import org.hibernate.search.backend.lucene.lowlevel.facet.impl.LongMultiValueFacetCounts; +import org.hibernate.search.backend.lucene.lowlevel.facet.impl.LongMultiValueRangeFacetCounts; import org.hibernate.search.backend.lucene.lowlevel.join.impl.NestedDocsProvider; import org.hibernate.search.util.common.data.Range; @@ -28,11 +31,6 @@ import org.apache.lucene.search.Query; import org.apache.lucene.util.NumericUtils; -import org.hibernate.search.backend.lucene.lowlevel.docvalues.impl.DoubleMultiValuesToSingleValuesSource; -import org.hibernate.search.backend.lucene.lowlevel.docvalues.impl.MultiValueMode; -import org.hibernate.search.backend.lucene.lowlevel.facet.impl.DoubleMultiValueRangeFacetCounts; -import org.hibernate.search.backend.lucene.lowlevel.facet.impl.LongMultiValueFacetCounts; - public class LuceneDoubleDomain implements LuceneNumericDomain { private static final LuceneNumericDomain INSTANCE = new LuceneDoubleDomain(); @@ -98,13 +96,19 @@ public Facets createTermsFacetCounts(String absoluteFieldPath, FacetsCollector f public Facets createRangeFacetCounts(String absoluteFieldPath, FacetsCollector facetsCollector, Collection> ranges, NestedDocsProvider nestedDocsProvider) throws IOException { - JoiningDoubleMultiValuesSource source = JoiningDoubleMultiValuesSource.fromDoubleField( + // As we don't need to apply any operation to terms except sometimes a sort, + // we can simply rely on raw, long values, whose order is the same as their corresponding double value. + // Values are ultimately converted back to the Double equivalent by calling sortedDocValueToTerm. + JoiningLongMultiValuesSource source = JoiningLongMultiValuesSource.fromLongField( absoluteFieldPath, nestedDocsProvider ); - return new DoubleMultiValueRangeFacetCounts( - absoluteFieldPath, - source, - facetsCollector, FacetCountsUtils.createDoubleRanges( ranges ) + return new LongMultiValueRangeFacetCounts( + absoluteFieldPath, source, + facetsCollector, + FacetCountsUtils.createLongRangesForFloatingPointValues( + ranges, NumericUtils::doubleToSortableLong, + Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY + ) ); } diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/lowlevel/impl/LuceneFloatDomain.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/lowlevel/impl/LuceneFloatDomain.java index 7a12fcdc0c8..fa48ba84a87 100644 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/lowlevel/impl/LuceneFloatDomain.java +++ b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/lowlevel/impl/LuceneFloatDomain.java @@ -10,9 +10,9 @@ import java.util.Collection; import java.util.Comparator; -import org.hibernate.search.backend.lucene.lowlevel.docvalues.impl.JoiningDoubleMultiValuesSource; import org.hibernate.search.backend.lucene.lowlevel.docvalues.impl.JoiningLongMultiValuesSource; import org.hibernate.search.backend.lucene.lowlevel.facet.impl.FacetCountsUtils; +import org.hibernate.search.backend.lucene.lowlevel.facet.impl.LongMultiValueRangeFacetCounts; import org.hibernate.search.backend.lucene.lowlevel.join.impl.NestedDocsProvider; import org.hibernate.search.util.common.data.Range; @@ -30,7 +30,6 @@ import org.hibernate.search.backend.lucene.lowlevel.docvalues.impl.DoubleMultiValuesToSingleValuesSource; import org.hibernate.search.backend.lucene.lowlevel.docvalues.impl.MultiValueMode; -import org.hibernate.search.backend.lucene.lowlevel.facet.impl.DoubleMultiValueRangeFacetCounts; import org.hibernate.search.backend.lucene.lowlevel.facet.impl.LongMultiValueFacetCounts; public class LuceneFloatDomain implements LuceneNumericDomain { @@ -98,12 +97,19 @@ public Facets createTermsFacetCounts(String absoluteFieldPath, FacetsCollector f public Facets createRangeFacetCounts(String absoluteFieldPath, FacetsCollector facetsCollector, Collection> ranges, NestedDocsProvider nestedDocsProvider) throws IOException { - JoiningDoubleMultiValuesSource source = JoiningDoubleMultiValuesSource.fromFloatField( + // As we don't need to apply any operation to terms except sometimes a sort, + // we can simply rely on raw, int values, whose order is the same as their corresponding float value. + // Values are ultimately converted back to the Float equivalent by calling sortedDocValueToTerm. + JoiningLongMultiValuesSource source = JoiningLongMultiValuesSource.fromIntField( absoluteFieldPath, nestedDocsProvider ); - return new DoubleMultiValueRangeFacetCounts( + return new LongMultiValueRangeFacetCounts( absoluteFieldPath, source, - facetsCollector, FacetCountsUtils.createDoubleRanges( ranges ) + facetsCollector, + FacetCountsUtils.createLongRangesForFloatingPointValues( + ranges, value -> (long) NumericUtils.floatToSortableInt( value ), + Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY + ) ); } diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/lowlevel/impl/LuceneIntegerDomain.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/lowlevel/impl/LuceneIntegerDomain.java index 266ac2d9cee..7c20ca5e083 100644 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/lowlevel/impl/LuceneIntegerDomain.java +++ b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/lowlevel/impl/LuceneIntegerDomain.java @@ -100,7 +100,8 @@ public Facets createRangeFacetCounts(String absoluteFieldPath, FacetsCollector f ); return new LongMultiValueRangeFacetCounts( absoluteFieldPath, source, - facetsCollector, FacetCountsUtils.createLongRanges( ranges ) + facetsCollector, + FacetCountsUtils.createLongRangesForIntegralValues( ranges ) ); } diff --git a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/lowlevel/impl/LuceneLongDomain.java b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/lowlevel/impl/LuceneLongDomain.java index 39933580830..6b05129f7e7 100644 --- a/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/lowlevel/impl/LuceneLongDomain.java +++ b/backend/lucene/src/main/java/org/hibernate/search/backend/lucene/types/lowlevel/impl/LuceneLongDomain.java @@ -100,7 +100,8 @@ public Facets createRangeFacetCounts(String absoluteFieldPath, FacetsCollector f ); return new LongMultiValueRangeFacetCounts( absoluteFieldPath, source, - facetsCollector, FacetCountsUtils.createLongRanges( ranges ) + facetsCollector, + FacetCountsUtils.createLongRangesForIntegralValues( ranges ) ); }