LUCENE-7610: Deprecate ValueSource methods in facets module

This commit is contained in:
Alan Woodward 2017-01-06 10:41:12 +00:00
parent 8b055382d6
commit 713b65d1dc
13 changed files with 361 additions and 208 deletions

View File

@ -79,6 +79,9 @@ API Changes
replaced with Expression#getDoubleValuesSource(). (Alan Woodward, Adrien
Grand)
* LUCENE-7610: The facets module now uses the DoubleValuesSource API, and
methods that take ValueSource parameters are deprecated (Alan Woodward)
New features
* LUCENE-5867: Added BooleanSimilarity. (Robert Muir, Adrien Grand)

View File

@ -16,9 +16,13 @@
*/
package org.apache.lucene.demo.facet;
import java.io.Closeable;
import java.io.IOException;
import java.text.ParseException;
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.document.DoublePoint;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.DoublePoint;
import org.apache.lucene.document.NumericDocValuesField;
import org.apache.lucene.expressions.Expression;
import org.apache.lucene.expressions.SimpleBindings;
@ -36,9 +40,9 @@ import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
@ -48,10 +52,6 @@ import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.SloppyMath;
import java.io.Closeable;
import java.io.IOException;
import java.text.ParseException;
/** Shows simple usage of dynamic range faceting, using the
* expressions module to calculate distance. */
public class DistanceFacetsExample implements Closeable {
@ -117,7 +117,7 @@ public class DistanceFacetsExample implements Closeable {
writer.close();
}
private ValueSource getDistanceValueSource() {
private DoubleValuesSource getDistanceValueSource() {
Expression distance;
try {
distance = JavascriptCompiler.compile(
@ -130,7 +130,7 @@ public class DistanceFacetsExample implements Closeable {
bindings.add(new SortField("latitude", SortField.Type.DOUBLE));
bindings.add(new SortField("longitude", SortField.Type.DOUBLE));
return distance.getValueSource(bindings);
return distance.getDoubleValuesSource(bindings);
}
/** Given a latitude and longitude (in degrees) and the
@ -224,7 +224,7 @@ public class DistanceFacetsExample implements Closeable {
// Passing no baseQuery means we drill down on all
// documents ("browse only"):
DrillDownQuery q = new DrillDownQuery(null);
final ValueSource vs = getDistanceValueSource();
final DoubleValuesSource vs = getDistanceValueSource();
q.add("field", range.getQuery(getBoundingBoxQuery(ORIGIN_LATITUDE, ORIGIN_LONGITUDE, range.max), vs));
DrillSideways ds = new DrillSideways(searcher, config, (TaxonomyReader) null) {
@Override

View File

@ -40,7 +40,7 @@
*
* <li> Range faceting {@link org.apache.lucene.facet.range.LongRangeFacetCounts}, {@link
* org.apache.lucene.facet.range.DoubleRangeFacetCounts} compute counts for a dynamic numeric
* range from a provided {@link org.apache.lucene.queries.function.ValueSource} (previously indexed
* range from a provided {@link org.apache.lucene.search.LongValuesSource} (previously indexed
* numeric field, or a dynamic expression such as distance).
* </ul>
* <p>

View File

@ -17,16 +17,16 @@
package org.apache.lucene.facet.range;
import java.io.IOException;
import java.util.Collections;
import java.util.Objects;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.ConstantScoreScorer;
import org.apache.lucene.search.ConstantScoreWeight;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.DoubleValues;
import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Scorer;
@ -95,9 +95,9 @@ public final class DoubleRange extends Range {
private static class ValueSourceQuery extends Query {
private final DoubleRange range;
private final Query fastMatchQuery;
private final ValueSource valueSource;
private final DoubleValuesSource valueSource;
ValueSourceQuery(DoubleRange range, Query fastMatchQuery, ValueSource valueSource) {
ValueSourceQuery(DoubleRange range, Query fastMatchQuery, DoubleValuesSource valueSource) {
this.range = range;
this.fastMatchQuery = fastMatchQuery;
this.valueSource = valueSource;
@ -158,11 +158,11 @@ public final class DoubleRange extends Range {
approximation = s.iterator();
}
final FunctionValues values = valueSource.getValues(Collections.emptyMap(), context);
final DoubleValues values = valueSource.getValues(context, null);
final TwoPhaseIterator twoPhase = new TwoPhaseIterator(approximation) {
@Override
public boolean matches() throws IOException {
return range.accept(values.doubleVal(approximation.docID()));
return values.advanceExact(approximation.docID()) && range.accept(values.doubleValue());
}
@Override
@ -177,8 +177,27 @@ public final class DoubleRange extends Range {
}
@Override
/**
* @deprecated Use {@link #getQuery(Query, DoubleValuesSource)}
*/
@Deprecated
public Query getQuery(final Query fastMatchQuery, final ValueSource valueSource) {
return new ValueSourceQuery(this, fastMatchQuery, valueSource.asDoubleValuesSource());
}
/**
* Create a Query that matches documents in this range
*
* The query will check all documents that match the provided match query,
* or every document in the index if the match query is null.
*
* If the value source is static, eg an indexed numeric field, it may be
* faster to use {@link org.apache.lucene.search.PointRangeQuery}
*
* @param fastMatchQuery a query to use as a filter
* @param valueSource the source of values for the range check
*/
public Query getQuery(Query fastMatchQuery, DoubleValuesSource valueSource) {
return new ValueSourceQuery(this, fastMatchQuery, valueSource);
}
}

View File

@ -17,22 +17,18 @@
package org.apache.lucene.facet.range;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import org.apache.lucene.document.DoubleDocValuesField; // javadocs
import org.apache.lucene.document.FloatDocValuesField; // javadocs
import org.apache.lucene.document.FloatDocValuesField;
import org.apache.lucene.facet.Facets;
import org.apache.lucene.facet.FacetsCollector.MatchingDocs;
import org.apache.lucene.facet.FacetsCollector;
import org.apache.lucene.facet.FacetsCollector.MatchingDocs;
import org.apache.lucene.index.IndexReaderContext;
import org.apache.lucene.index.ReaderUtil;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.valuesource.DoubleFieldSource;
import org.apache.lucene.queries.function.valuesource.FloatFieldSource; // javadocs
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.DoubleValues;
import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Scorer;
@ -41,46 +37,70 @@ import org.apache.lucene.util.NumericUtils;
/** {@link Facets} implementation that computes counts for
* dynamic double ranges from a provided {@link
* ValueSource}, using {@link FunctionValues#doubleVal}. Use
* this for dimensions that change in real-time (e.g. a
* DoubleValuesSource}. Use this for dimensions that change in real-time (e.g. a
* relative time based dimension like "Past day", "Past 2
* days", etc.) or that change for each request (e.g.
* distance from the user's location, "&lt; 1 km", "&lt; 2 km",
* etc.).
*
* <p> If you had indexed your field using {@link
* FloatDocValuesField} then pass {@link FloatFieldSource}
* as the {@link ValueSource}; if you used {@link
* DoubleDocValuesField} then pass {@link
* DoubleFieldSource} (this is the default used when you
* pass just a the field name).
* If you have indexed your field using {@link
* FloatDocValuesField}, then you should use a DoubleValuesSource
* generated from {@link DoubleValuesSource#fromFloatField(String)}.
*
* @lucene.experimental */
public class DoubleRangeFacetCounts extends RangeFacetCounts {
/** Create {@code RangeFacetCounts}, using {@link
* DoubleFieldSource} from the specified field. */
/**
* Create {@code RangeFacetCounts}, using {@link DoubleValues} from the specified field.
*
* N.B This assumes that the field was indexed with {@link org.apache.lucene.document.DoubleDocValuesField}.
* For float-valued fields, use {@link #DoubleRangeFacetCounts(String, DoubleValuesSource, FacetsCollector, DoubleRange...)}
*/
public DoubleRangeFacetCounts(String field, FacetsCollector hits, DoubleRange... ranges) throws IOException {
this(field, new DoubleFieldSource(field), hits, ranges);
this(field, DoubleValuesSource.fromDoubleField(field), hits, ranges);
}
/** Create {@code RangeFacetCounts}, using the provided
* {@link ValueSource}. */
/**
* Create {@code RangeFacetCounts}, using the provided {@link ValueSource}.
*
* @deprecated Use {@link #DoubleRangeFacetCounts(String, DoubleValuesSource, FacetsCollector, DoubleRange...)}
* */
public DoubleRangeFacetCounts(String field, ValueSource valueSource, FacetsCollector hits, DoubleRange... ranges) throws IOException {
this(field, valueSource, hits, null, ranges);
}
/** Create {@code RangeFacetCounts}, using the provided
* {@link ValueSource}, and using the provided Query as
* a fastmatch: only documents passing the filter are
* checked for the matching ranges. The filter must be
* random access (implement {@link DocIdSet#bits}). */
/**
* Create {@code RangeFacetCounts} using the provided {@link DoubleValuesSource}
*/
public DoubleRangeFacetCounts(String field, DoubleValuesSource valueSource, FacetsCollector hits, DoubleRange... ranges) throws IOException {
this(field, valueSource, hits, null, ranges);
}
/**
* Create {@code RangeFacetCounts}, using the provided
* {@link ValueSource}, and using the provided Query as
* a fastmatch: only documents matching the query are
* checked for the matching ranges.
*
* @deprecated Use ({@link #DoubleRangeFacetCounts(String, DoubleValuesSource, FacetsCollector, Query, DoubleRange...)}
*/
@Deprecated
public DoubleRangeFacetCounts(String field, ValueSource valueSource, FacetsCollector hits, Query fastMatchQuery, DoubleRange... ranges) throws IOException {
this(field, valueSource.asDoubleValuesSource(), hits, fastMatchQuery, ranges);
}
/**
* Create {@code RangeFacetCounts}, using the provided
* {@link DoubleValuesSource}, and using the provided Query as
* a fastmatch: only documents matching the query are
* checked for the matching ranges.
*/
public DoubleRangeFacetCounts(String field, DoubleValuesSource valueSource, FacetsCollector hits, Query fastMatchQuery, DoubleRange... ranges) throws IOException {
super(field, ranges, fastMatchQuery);
count(valueSource, hits.getMatchingDocs());
}
private void count(ValueSource valueSource, List<MatchingDocs> matchingDocs) throws IOException {
private void count(DoubleValuesSource valueSource, List<MatchingDocs> matchingDocs) throws IOException {
DoubleRange[] ranges = (DoubleRange[]) this.ranges;
@ -96,7 +116,7 @@ public class DoubleRangeFacetCounts extends RangeFacetCounts {
int missingCount = 0;
for (MatchingDocs hits : matchingDocs) {
FunctionValues fv = valueSource.getValues(Collections.emptyMap(), hits.context);
DoubleValues fv = valueSource.getValues(hits.context, null);
totCount += hits.totalHits;
final DocIdSetIterator fastMatchDocs;
@ -129,8 +149,8 @@ public class DoubleRangeFacetCounts extends RangeFacetCounts {
}
}
// Skip missing docs:
if (fv.exists(doc)) {
counter.add(NumericUtils.doubleToSortableLong(fv.doubleVal(doc)));
if (fv.advanceExact(doc)) {
counter.add(NumericUtils.doubleToSortableLong(fv.doubleValue()));
} else {
missingCount++;
}

View File

@ -17,17 +17,17 @@
package org.apache.lucene.facet.range;
import java.io.IOException;
import java.util.Collections;
import java.util.Objects;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.ConstantScoreScorer;
import org.apache.lucene.search.ConstantScoreWeight;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.LongValues;
import org.apache.lucene.search.LongValuesSource;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.TwoPhaseIterator;
@ -87,9 +87,9 @@ public final class LongRange extends Range {
private static class ValueSourceQuery extends Query {
private final LongRange range;
private final Query fastMatchQuery;
private final ValueSource valueSource;
private final LongValuesSource valueSource;
ValueSourceQuery(LongRange range, Query fastMatchQuery, ValueSource valueSource) {
ValueSourceQuery(LongRange range, Query fastMatchQuery, LongValuesSource valueSource) {
this.range = range;
this.fastMatchQuery = fastMatchQuery;
this.valueSource = valueSource;
@ -150,11 +150,11 @@ public final class LongRange extends Range {
approximation = s.iterator();
}
final FunctionValues values = valueSource.getValues(Collections.emptyMap(), context);
final LongValues values = valueSource.getValues(context, null);
final TwoPhaseIterator twoPhase = new TwoPhaseIterator(approximation) {
@Override
public boolean matches() throws IOException {
return range.accept(values.longVal(approximation.docID()));
return values.advanceExact(approximation.docID()) && range.accept(values.longValue());
}
@Override
@ -169,8 +169,28 @@ public final class LongRange extends Range {
}
@Override
/**
* @deprecated Use {@link #getQuery(Query, LongValuesSource)}
*/
@Deprecated
public Query getQuery(final Query fastMatchQuery, final ValueSource valueSource) {
return new ValueSourceQuery(this, fastMatchQuery, valueSource.asLongValuesSource());
}
/**
* Create a Query that matches documents in this range
*
* The query will check all documents that match the provided match query,
* or every document in the index if the match query is null.
*
* If the value source is static, eg an indexed numeric field, it may be
* faster to use {@link org.apache.lucene.search.PointRangeQuery}
*
* @param fastMatchQuery a query to use as a filter
* @param valueSource the source of values for the range check
*/
public Query getQuery(Query fastMatchQuery, LongValuesSource valueSource) {
return new ValueSourceQuery(this, fastMatchQuery, valueSource);
}
}

View File

@ -17,27 +17,25 @@
package org.apache.lucene.facet.range;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import org.apache.lucene.facet.Facets;
import org.apache.lucene.facet.FacetsCollector.MatchingDocs;
import org.apache.lucene.facet.FacetsCollector;
import org.apache.lucene.facet.FacetsCollector.MatchingDocs;
import org.apache.lucene.index.IndexReaderContext;
import org.apache.lucene.index.ReaderUtil;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.valuesource.LongFieldSource;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.LongValues;
import org.apache.lucene.search.LongValuesSource;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.Weight;
/** {@link Facets} implementation that computes counts for
* dynamic long ranges from a provided {@link ValueSource},
* using {@link FunctionValues#longVal}. Use
* dynamic long ranges from a provided {@link LongValuesSource}. Use
* this for dimensions that change in real-time (e.g. a
* relative time based dimension like "Past day", "Past 2
* days", etc.) or that change for each request (e.g.
@ -48,28 +46,49 @@ import org.apache.lucene.search.Weight;
public class LongRangeFacetCounts extends RangeFacetCounts {
/** Create {@code LongRangeFacetCounts}, using {@link
* LongFieldSource} from the specified field. */
* LongValuesSource} from the specified field. */
public LongRangeFacetCounts(String field, FacetsCollector hits, LongRange... ranges) throws IOException {
this(field, new LongFieldSource(field), hits, ranges);
this(field, LongValuesSource.fromLongField(field), hits, ranges);
}
/**
* Create {@code RangeFacetCounts}, using the provided {@link ValueSource}.
*
* @deprecated Use {@link #LongRangeFacetCounts(String, LongValuesSource, FacetsCollector, LongRange...)}
*/
@Deprecated
public LongRangeFacetCounts(String field, ValueSource valueSource, FacetsCollector hits, LongRange... ranges) throws IOException {
this(field, valueSource.asLongValuesSource(), hits, null, ranges);
}
/** Create {@code RangeFacetCounts}, using the provided
* {@link ValueSource}. */
public LongRangeFacetCounts(String field, ValueSource valueSource, FacetsCollector hits, LongRange... ranges) throws IOException {
public LongRangeFacetCounts(String field, LongValuesSource valueSource, FacetsCollector hits, LongRange... ranges) throws IOException {
this(field, valueSource, hits, null, ranges);
}
/**
* Create {@code RangeFacetCounts}, using the provided {@link ValueSource}.
*
* @deprecated Use {@link #LongRangeFacetCounts(String, LongValuesSource, FacetsCollector, Query, LongRange...)}
*/
@Deprecated
public LongRangeFacetCounts(String field, ValueSource valueSource, FacetsCollector hits, Query fastMatchQuery, LongRange... ranges) throws IOException {
this(field, valueSource.asLongValuesSource(), hits, fastMatchQuery, ranges);
}
/** Create {@code RangeFacetCounts}, using the provided
* {@link ValueSource}, and using the provided Filter as
* a fastmatch: only documents passing the filter are
* checked for the matching ranges. The filter must be
* random access (implement {@link DocIdSet#bits}). */
public LongRangeFacetCounts(String field, ValueSource valueSource, FacetsCollector hits, Query fastMatchQuery, LongRange... ranges) throws IOException {
public LongRangeFacetCounts(String field, LongValuesSource valueSource, FacetsCollector hits, Query fastMatchQuery, LongRange... ranges) throws IOException {
super(field, ranges, fastMatchQuery);
count(valueSource, hits.getMatchingDocs());
}
private void count(ValueSource valueSource, List<MatchingDocs> matchingDocs) throws IOException {
private void count(LongValuesSource valueSource, List<MatchingDocs> matchingDocs) throws IOException {
LongRange[] ranges = (LongRange[]) this.ranges;
@ -77,7 +96,7 @@ public class LongRangeFacetCounts extends RangeFacetCounts {
int missingCount = 0;
for (MatchingDocs hits : matchingDocs) {
FunctionValues fv = valueSource.getValues(Collections.emptyMap(), hits.context);
LongValues fv = valueSource.getValues(hits.context, null);
totCount += hits.totalHits;
final DocIdSetIterator fastMatchDocs;
@ -109,8 +128,8 @@ public class LongRangeFacetCounts extends RangeFacetCounts {
}
}
// Skip missing docs:
if (fv.exists(doc)) {
counter.add(fv.longVal(doc));
if (fv.advanceExact(doc)) {
counter.add(fv.longValue());
} else {
missingCount++;
}

View File

@ -16,10 +16,6 @@
*/
package org.apache.lucene.facet.range;
import org.apache.lucene.facet.DrillDownQuery; // javadocs
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.Query;
/** Base class for a single labeled range.
*
* @lucene.experimental */
@ -36,33 +32,6 @@ public abstract class Range {
this.label = label;
}
/** Returns a new {@link Query} accepting only documents
* in this range. This query might not be very efficient
* when run on its own since it is optimized towards
* random-access, so it is best used either with
* {@link DrillDownQuery#add(String, Query) DrillDownQuery}
* or when intersected with another query that can lead the
* iteration. If the {@link ValueSource} is static, e.g. an
* indexed numeric field, then it may be more efficient to use
* {@link org.apache.lucene.search.PointRangeQuery}. The provided fastMatchQuery,
* if non-null, will first be consulted, and only if
* that is set for each document will the range then be
* checked. */
public abstract Query getQuery(Query fastMatchQuery, ValueSource valueSource);
/** Returns a new {@link Query} accepting only documents
* in this range. This query might not be very efficient
* when run on its own since it is optimized towards
* random-access, so it is best used either with
* {@link DrillDownQuery#add(String, Query) DrillDownQuery}
* or when intersected with another query that can lead the
* iteration. If the {@link ValueSource} is static, e.g. an
* indexed numeric field, then it may be more efficient to
* use {@link org.apache.lucene.search.PointRangeQuery}. */
public Query getQuery(ValueSource valueSource) {
return getQuery(null, valueSource);
}
/** Invoke this for a useless range. */
protected void failNoMatch() {
throw new IllegalArgumentException("range \"" + label + "\" matches nothing");

View File

@ -1,53 +0,0 @@
/*
* 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.apache.lucene.facet.taxonomy;
import java.io.IOException;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Scorer;
class FakeScorer extends Scorer {
float score;
int doc = -1;
int freq = 1;
FakeScorer() {
super(null);
}
@Override
public int docID() {
return doc;
}
@Override
public DocIdSetIterator iterator() {
throw new UnsupportedOperationException();
}
@Override
public int freq() throws IOException {
return freq;
}
@Override
public float score() throws IOException {
return score;
}
}

View File

@ -17,7 +17,6 @@
package org.apache.lucene.facet.taxonomy;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -29,6 +28,8 @@ import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.DoubleValues;
import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.util.IntsRef;
@ -39,52 +40,94 @@ import org.apache.lucene.util.IntsRef;
public class TaxonomyFacetSumValueSource extends FloatTaxonomyFacets {
private final OrdinalsReader ordinalsReader;
/** Aggreggates float facet values from the provided
/**
* Aggreggates double facet values from the provided
* {@link ValueSource}, pulling ordinals using {@link
* DocValuesOrdinalsReader} against the default indexed
* facet field {@link
* FacetsConfig#DEFAULT_INDEX_FIELD_NAME}. */
* FacetsConfig#DEFAULT_INDEX_FIELD_NAME}.
*
* @deprecated {@link #TaxonomyFacetSumValueSource(TaxonomyReader, FacetsConfig, FacetsCollector, DoubleValuesSource)}
*/
@Deprecated
public TaxonomyFacetSumValueSource(TaxonomyReader taxoReader, FacetsConfig config,
FacetsCollector fc, ValueSource valueSource) throws IOException {
this(new DocValuesOrdinalsReader(FacetsConfig.DEFAULT_INDEX_FIELD_NAME), taxoReader, config, fc, valueSource);
}
/** Aggreggates float facet values from the provided
/**
* Aggreggates double facet values from the provided
* {@link DoubleValuesSource}, pulling ordinals using {@link
* DocValuesOrdinalsReader} against the default indexed
* facet field {@link FacetsConfig#DEFAULT_INDEX_FIELD_NAME}.
*/
public TaxonomyFacetSumValueSource(TaxonomyReader taxoReader, FacetsConfig config,
FacetsCollector fc, DoubleValuesSource valueSource) throws IOException {
this(new DocValuesOrdinalsReader(FacetsConfig.DEFAULT_INDEX_FIELD_NAME), taxoReader, config, fc, valueSource);
}
/**
* Aggreggates float facet values from the provided
* {@link ValueSource}, and pulls ordinals from the
* provided {@link OrdinalsReader}. */
* provided {@link OrdinalsReader}.
*
* @deprecated use {@link #TaxonomyFacetSumValueSource(OrdinalsReader, TaxonomyReader, FacetsConfig, FacetsCollector, DoubleValuesSource)}
*/
@Deprecated
public TaxonomyFacetSumValueSource(OrdinalsReader ordinalsReader, TaxonomyReader taxoReader,
FacetsConfig config, FacetsCollector fc, ValueSource valueSource) throws IOException {
super(ordinalsReader.getIndexFieldName(), taxoReader, config);
this.ordinalsReader = ordinalsReader;
sumValues(fc.getMatchingDocs(), fc.getKeepScores(), valueSource);
sumValues(fc.getMatchingDocs(), fc.getKeepScores(), valueSource.asDoubleValuesSource());
}
private final void sumValues(List<MatchingDocs> matchingDocs, boolean keepScores, ValueSource valueSource) throws IOException {
final FakeScorer scorer = new FakeScorer();
Map<String, Scorer> context = new HashMap<>();
if (keepScores) {
context.put("scorer", scorer);
}
/**
* Aggreggates float facet values from the provided
* {@link DoubleValuesSource}, and pulls ordinals from the
* provided {@link OrdinalsReader}.
*/
public TaxonomyFacetSumValueSource(OrdinalsReader ordinalsReader, TaxonomyReader taxoReader,
FacetsConfig config, FacetsCollector fc, DoubleValuesSource vs) throws IOException {
super(ordinalsReader.getIndexFieldName(), taxoReader, config);
this.ordinalsReader = ordinalsReader;
sumValues(fc.getMatchingDocs(), fc.getKeepScores(), vs);
}
private static DoubleValues scores(MatchingDocs hits) {
return new DoubleValues() {
int index = -1;
@Override
public double doubleValue() throws IOException {
return hits.scores[index];
}
@Override
public boolean advanceExact(int doc) throws IOException {
index++;
return true;
}
};
}
private void sumValues(List<MatchingDocs> matchingDocs, boolean keepScores, DoubleValuesSource valueSource) throws IOException {
IntsRef scratch = new IntsRef();
for(MatchingDocs hits : matchingDocs) {
OrdinalsReader.OrdinalsSegmentReader ords = ordinalsReader.getReader(hits.context);
int scoresIdx = 0;
float[] scores = hits.scores;
FunctionValues functionValues = valueSource.getValues(context, hits.context);
DoubleValues scores = keepScores ? scores(hits) : null;
DoubleValues functionValues = valueSource.getValues(hits.context, scores);
DocIdSetIterator docs = hits.bits.iterator();
int doc;
while ((doc = docs.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
ords.get(doc, scratch);
if (keepScores) {
scorer.doc = doc;
scorer.score = scores[scoresIdx++];
}
float value = (float) functionValues.doubleVal(doc);
for(int i=0;i<scratch.length;i++) {
values[scratch.ints[i]] += value;
if (functionValues.advanceExact(doc)) {
float value = (float) functionValues.doubleValue();
for (int i = 0; i < scratch.length; i++) {
values[scratch.ints[i]] += value;
}
}
}
}
@ -92,9 +135,13 @@ public class TaxonomyFacetSumValueSource extends FloatTaxonomyFacets {
rollup();
}
/** {@link ValueSource} that returns the score for each
/**
* {@link ValueSource} that returns the score for each
* hit; use this to aggregate the sum of all hit scores
* for each facet label. */
* for each facet label.
*
* @deprecated Use {@link DoubleValuesSource#SCORES}
*/
public static class ScoreValueSource extends ValueSource {
/** Sole constructor. */

View File

@ -28,8 +28,8 @@ import org.apache.lucene.document.DoublePoint;
import org.apache.lucene.document.LongPoint;
import org.apache.lucene.document.NumericDocValuesField;
import org.apache.lucene.facet.DrillDownQuery;
import org.apache.lucene.facet.DrillSideways.DrillSidewaysResult;
import org.apache.lucene.facet.DrillSideways;
import org.apache.lucene.facet.DrillSideways.DrillSidewaysResult;
import org.apache.lucene.facet.FacetField;
import org.apache.lucene.facet.FacetResult;
import org.apache.lucene.facet.FacetTestCase;
@ -46,11 +46,11 @@ import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.RandomIndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
import org.apache.lucene.queries.function.valuesource.DoubleFieldSource;
import org.apache.lucene.queries.function.valuesource.LongFieldSource;
import org.apache.lucene.search.DoubleValues;
import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
@ -708,7 +708,7 @@ public class TestRangeFacetCounts extends FacetTestCase {
}
public void testCustomDoublesValueSource() throws Exception {
public void testCustomDoubleValuesSource() throws Exception {
Directory dir = newDirectory();
RandomIndexWriter writer = new RandomIndexWriter(random(), dir);
@ -720,33 +720,30 @@ public class TestRangeFacetCounts extends FacetTestCase {
// Test wants 3 docs in one segment:
writer.forceMerge(1);
final ValueSource vs = new ValueSource() {
@SuppressWarnings("rawtypes")
@Override
public FunctionValues getValues(Map ignored, LeafReaderContext ignored2) {
return new DoubleDocValues(null) {
@Override
public double doubleVal(int doc) {
return doc+1;
}
};
}
final DoubleValuesSource vs = new DoubleValuesSource() {
@Override
public boolean equals(Object o) {
return o != null && getClass() == o.getClass();
}
@Override
public DoubleValues getValues(LeafReaderContext ctx, DoubleValues scores) throws IOException {
return new DoubleValues() {
int doc = -1;
@Override
public double doubleValue() throws IOException {
return doc + 1;
}
@Override
public int hashCode() {
return getClass().hashCode();
}
@Override
public boolean advanceExact(int doc) throws IOException {
this.doc = doc;
return true;
}
};
}
@Override
public String description() {
throw new UnsupportedOperationException();
}
};
@Override
public boolean needsScores() {
return false;
}
};
FacetsConfig config = new FacetsConfig();

View File

@ -52,6 +52,7 @@ import org.apache.lucene.queries.function.valuesource.IntFieldSource;
import org.apache.lucene.queries.function.valuesource.LongFieldSource;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
@ -266,7 +267,7 @@ public class TestTaxonomyFacetSumValueSource extends FacetTestCase {
TopDocs td = FacetsCollector.search(newSearcher(r), csq, 10, fc);
Facets facets = new TaxonomyFacetSumValueSource(taxoReader, config, fc, new TaxonomyFacetSumValueSource.ScoreValueSource());
Facets facets = new TaxonomyFacetSumValueSource(taxoReader, config, fc, DoubleValuesSource.SCORES);
int expected = (int) (td.getMaxScore() * td.totalHits);
assertEquals(expected, facets.getSpecificValue("dim", "a").intValue());
@ -408,7 +409,7 @@ public class TestTaxonomyFacetSumValueSource extends FacetTestCase {
FacetsCollector.search(newSearcher(r), new MatchAllDocsQuery(), 10, fc);
Facets facets1 = getTaxonomyFacetCounts(taxoReader, config, fc);
Facets facets2 = new TaxonomyFacetSumValueSource(new DocValuesOrdinalsReader("$b"), taxoReader, config, fc, new TaxonomyFacetSumValueSource.ScoreValueSource());
Facets facets2 = new TaxonomyFacetSumValueSource(new DocValuesOrdinalsReader("$b"), taxoReader, config, fc, DoubleValuesSource.SCORES);
assertEquals(r.maxDoc(), facets1.getTopChildren(10, "a").value.intValue());
assertEquals(r.maxDoc(), facets2.getTopChildren(10, "b").value.doubleValue(), 1E-10);

View File

@ -17,13 +17,20 @@
package org.apache.lucene.queries.function;
import java.io.IOException;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.DoubleValues;
import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.FieldComparator;
import org.apache.lucene.search.FieldComparatorSource;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.LongValues;
import org.apache.lucene.search.LongValuesSource;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.SimpleFieldComparator;
import org.apache.lucene.search.SortField;
@ -78,6 +85,110 @@ public abstract class ValueSource {
return context;
}
private static class FakeScorer extends Scorer {
int current = -1;
float score = 0;
FakeScorer() {
super(null);
}
@Override
public int docID() {
return current;
}
@Override
public float score() throws IOException {
return score;
}
@Override
public int freq() throws IOException {
throw new UnsupportedOperationException();
}
@Override
public DocIdSetIterator iterator() {
throw new UnsupportedOperationException();
}
}
/**
* Expose this ValueSource as a LongValuesSource
*/
public LongValuesSource asLongValuesSource() {
return new LongValuesSource() {
@Override
public LongValues getValues(LeafReaderContext ctx, DoubleValues scores) throws IOException {
Map context = new IdentityHashMap<>();
FakeScorer scorer = new FakeScorer();
context.put("scorer", scorer);
final FunctionValues fv = ValueSource.this.getValues(context, ctx);
return new LongValues() {
@Override
public long longValue() throws IOException {
return fv.longVal(scorer.current);
}
@Override
public boolean advanceExact(int doc) throws IOException {
scorer.current = doc;
if (scores != null && scores.advanceExact(doc))
scorer.score = (float) scores.doubleValue();
else
scorer.score = 0;
return fv.exists(doc);
}
};
}
@Override
public boolean needsScores() {
return false;
}
};
}
/**
* Expose this ValueSource as a DoubleValuesSource
*/
public DoubleValuesSource asDoubleValuesSource() {
return new DoubleValuesSource() {
@Override
public DoubleValues getValues(LeafReaderContext ctx, DoubleValues scores) throws IOException {
Map context = new HashMap<>();
FakeScorer scorer = new FakeScorer();
context.put("scorer", scorer);
FunctionValues fv = ValueSource.this.getValues(context, ctx);
return new DoubleValues() {
@Override
public double doubleValue() throws IOException {
return fv.doubleVal(scorer.current);
}
@Override
public boolean advanceExact(int doc) throws IOException {
scorer.current = doc;
if (scores != null && scores.advanceExact(doc)) {
scorer.score = (float) scores.doubleValue();
}
else
scorer.score = 0;
return fv.exists(doc);
}
};
}
@Override
public boolean needsScores() {
return true; // be on the safe side
}
};
}
//
// Sorting by function