You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-commits@lucene.apache.org by do...@apache.org on 2007/06/05 18:29:42 UTC
svn commit: r544546 [1/2] - in /lucene/java/trunk: ./
src/java/org/apache/lucene/search/
src/java/org/apache/lucene/search/function/ src/java/org/apache/lucene/util/
src/test/org/apache/lucene/search/function/
Author: doronc
Date: Tue Jun 5 09:29:35 2007
New Revision: 544546
URL: http://svn.apache.org/viewvc?view=rev&rev=544546
Log:
LUCENE-446: Added Solr's search.function for scores based on field
values, plus CustomScoreQuery for simple score (post) customization.
Added:
lucene/java/trunk/src/java/org/apache/lucene/search/function/
lucene/java/trunk/src/java/org/apache/lucene/search/function/ByteFieldSource.java (with props)
lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java (with props)
lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java (with props)
lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldCacheSource.java (with props)
lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldScoreQuery.java (with props)
lucene/java/trunk/src/java/org/apache/lucene/search/function/FloatFieldSource.java (with props)
lucene/java/trunk/src/java/org/apache/lucene/search/function/IntFieldSource.java (with props)
lucene/java/trunk/src/java/org/apache/lucene/search/function/OrdFieldSource.java (with props)
lucene/java/trunk/src/java/org/apache/lucene/search/function/ReverseOrdFieldSource.java (with props)
lucene/java/trunk/src/java/org/apache/lucene/search/function/ShortFieldSource.java (with props)
lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSource.java (with props)
lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSourceQuery.java (with props)
lucene/java/trunk/src/java/org/apache/lucene/search/function/package.html (with props)
lucene/java/trunk/src/test/org/apache/lucene/search/function/
lucene/java/trunk/src/test/org/apache/lucene/search/function/FunctionTestSetup.java (with props)
lucene/java/trunk/src/test/org/apache/lucene/search/function/TestCustomScoreQuery.java (with props)
lucene/java/trunk/src/test/org/apache/lucene/search/function/TestFieldScoreQuery.java (with props)
lucene/java/trunk/src/test/org/apache/lucene/search/function/TestOrdValues.java (with props)
Modified:
lucene/java/trunk/CHANGES.txt
lucene/java/trunk/src/java/org/apache/lucene/search/FieldCache.java
lucene/java/trunk/src/java/org/apache/lucene/search/FieldCacheImpl.java
lucene/java/trunk/src/java/org/apache/lucene/util/ToStringUtils.java
Modified: lucene/java/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/java/trunk/CHANGES.txt?view=diff&rev=544546&r1=544545&r2=544546
==============================================================================
--- lucene/java/trunk/CHANGES.txt (original)
+++ lucene/java/trunk/CHANGES.txt Tue Jun 5 09:29:35 2007
@@ -186,6 +186,10 @@
on the remote side of the RMI connection.
(Matt Ericson via Otis Gospodnetic)
+ 8. LUCENE-446: Added Solr's search.function for scores based on field
+ values, plus CustomScoreQuery for simple score (post) customization.
+ (Yonik Seeley, Doron Cohen)
+
Optimizations
1. LUCENE-761: The proxStream is now cloned lazily in SegmentTermPositions
Modified: lucene/java/trunk/src/java/org/apache/lucene/search/FieldCache.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/FieldCache.java?view=diff&rev=544546&r1=544545&r2=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/FieldCache.java (original)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/FieldCache.java Tue Jun 5 09:29:35 2007
@@ -53,6 +53,22 @@
}
}
+ /** Interface to parse bytes from document fields.
+ * @see FieldCache#getBytes(IndexReader, String, FieldCache.ByteParser)
+ */
+ public interface ByteParser {
+ /** Return a single Byte representation of this field's value. */
+ public byte parseByte(String string);
+ }
+
+ /** Interface to parse shorts from document fields.
+ * @see FieldCache#getShorts(IndexReader, String, FieldCache.ShortParser)
+ */
+ public interface ShortParser {
+ /** Return a short representation of this field's value. */
+ public short parseShort(String string);
+ }
+
/** Interface to parse ints from document fields.
* @see FieldCache#getInts(IndexReader, String, FieldCache.IntParser)
*/
@@ -71,6 +87,56 @@
/** Expert: The cache used internally by sorting and range query classes. */
public static FieldCache DEFAULT = new FieldCacheImpl();
+
+ /** Checks the internal cache for an appropriate entry, and if none is
+ * found, reads the terms in <code>field</code> as a single byte and returns an array
+ * of size <code>reader.maxDoc()</code> of the value each document
+ * has in the given field.
+ * @param reader Used to get field values.
+ * @param field Which field contains the single byte values.
+ * @return The values in the given field for each document.
+ * @throws IOException If any error occurs.
+ */
+ public byte[] getBytes (IndexReader reader, String field)
+ throws IOException;
+
+ /** Checks the internal cache for an appropriate entry, and if none is found,
+ * reads the terms in <code>field</code> as bytes and returns an array of
+ * size <code>reader.maxDoc()</code> of the value each document has in the
+ * given field.
+ * @param reader Used to get field values.
+ * @param field Which field contains the bytes.
+ * @param parser Computes byte for string values.
+ * @return The values in the given field for each document.
+ * @throws IOException If any error occurs.
+ */
+ public byte[] getBytes (IndexReader reader, String field, ByteParser parser)
+ throws IOException;
+
+ /** Checks the internal cache for an appropriate entry, and if none is
+ * found, reads the terms in <code>field</code> as shorts and returns an array
+ * of size <code>reader.maxDoc()</code> of the value each document
+ * has in the given field.
+ * @param reader Used to get field values.
+ * @param field Which field contains the shorts.
+ * @return The values in the given field for each document.
+ * @throws IOException If any error occurs.
+ */
+ public short[] getShorts (IndexReader reader, String field)
+ throws IOException;
+
+ /** Checks the internal cache for an appropriate entry, and if none is found,
+ * reads the terms in <code>field</code> as shorts and returns an array of
+ * size <code>reader.maxDoc()</code> of the value each document has in the
+ * given field.
+ * @param reader Used to get field values.
+ * @param field Which field contains the shorts.
+ * @param parser Computes short for string values.
+ * @return The values in the given field for each document.
+ * @throws IOException If any error occurs.
+ */
+ public short[] getShorts (IndexReader reader, String field, ShortParser parser)
+ throws IOException;
/** Checks the internal cache for an appropriate entry, and if none is
* found, reads the terms in <code>field</code> as integers and returns an array
Modified: lucene/java/trunk/src/java/org/apache/lucene/search/FieldCacheImpl.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/FieldCacheImpl.java?view=diff&rev=544546&r1=544545&r2=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/FieldCacheImpl.java (original)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/FieldCacheImpl.java Tue Jun 5 09:29:35 2007
@@ -131,18 +131,108 @@
}
}
+ private static final ByteParser BYTE_PARSER = new ByteParser() {
+ public byte parseByte(String value) {
+ return Byte.parseByte(value);
+ }
+ };
+
+ private static final ShortParser SHORT_PARSER = new ShortParser() {
+ public short parseShort(String value) {
+ return Short.parseShort(value);
+ }
+ };
+
private static final IntParser INT_PARSER = new IntParser() {
public int parseInt(String value) {
return Integer.parseInt(value);
}
- };
+ };
private static final FloatParser FLOAT_PARSER = new FloatParser() {
public float parseFloat(String value) {
return Float.parseFloat(value);
}
- };
+ };
+
+ // inherit javadocs
+ public byte[] getBytes (IndexReader reader, String field) throws IOException {
+ return getBytes(reader, field, BYTE_PARSER);
+ }
+
+ // inherit javadocs
+ public byte[] getBytes(IndexReader reader, String field, ByteParser parser)
+ throws IOException {
+ return (byte[]) bytesCache.get(reader, new Entry(field, parser));
+ }
+
+ Cache bytesCache = new Cache() {
+
+ protected Object createValue(IndexReader reader, Object entryKey)
+ throws IOException {
+ Entry entry = (Entry) entryKey;
+ String field = entry.field;
+ ByteParser parser = (ByteParser) entry.custom;
+ final byte[] retArray = new byte[reader.maxDoc()];
+ TermDocs termDocs = reader.termDocs();
+ TermEnum termEnum = reader.terms (new Term (field, ""));
+ try {
+ do {
+ Term term = termEnum.term();
+ if (term==null || term.field() != field) break;
+ byte termval = parser.parseByte(term.text());
+ termDocs.seek (termEnum);
+ while (termDocs.next()) {
+ retArray[termDocs.doc()] = termval;
+ }
+ } while (termEnum.next());
+ } finally {
+ termDocs.close();
+ termEnum.close();
+ }
+ return retArray;
+ }
+ };
+
+ // inherit javadocs
+ public short[] getShorts (IndexReader reader, String field) throws IOException {
+ return getShorts(reader, field, SHORT_PARSER);
+ }
+
+ // inherit javadocs
+ public short[] getShorts(IndexReader reader, String field, ShortParser parser)
+ throws IOException {
+ return (short[]) shortsCache.get(reader, new Entry(field, parser));
+ }
+ Cache shortsCache = new Cache() {
+
+ protected Object createValue(IndexReader reader, Object entryKey)
+ throws IOException {
+ Entry entry = (Entry) entryKey;
+ String field = entry.field;
+ ShortParser parser = (ShortParser) entry.custom;
+ final short[] retArray = new short[reader.maxDoc()];
+ TermDocs termDocs = reader.termDocs();
+ TermEnum termEnum = reader.terms (new Term (field, ""));
+ try {
+ do {
+ Term term = termEnum.term();
+ if (term==null || term.field() != field) break;
+ short termval = parser.parseShort(term.text());
+ termDocs.seek (termEnum);
+ while (termDocs.next()) {
+ retArray[termDocs.doc()] = termval;
+ }
+ } while (termEnum.next());
+ } finally {
+ termDocs.close();
+ termEnum.close();
+ }
+ return retArray;
+ }
+ };
+
// inherit javadocs
public int[] getInts (IndexReader reader, String field) throws IOException {
return getInts(reader, field, INT_PARSER);
Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/ByteFieldSource.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/ByteFieldSource.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/ByteFieldSource.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/ByteFieldSource.java Tue Jun 5 09:29:35 2007
@@ -0,0 +1,105 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.FieldCache;
+import org.apache.lucene.search.function.DocValues;
+
+import java.io.IOException;
+
+/**
+ * Expert: obtains single byte field values from the
+ * {@link org.apache.lucene.search.FieldCache FieldCache}
+ * using <code>getBytes()</code> and makes those values
+ * available as other numeric types, casting as needed.
+ *
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental.
+ * The APIs introduced here might change in the future and will not be
+ * supported anymore in such a case.</font>
+ *
+ * @see org.apache.lucene.search.function.FieldCacheSource for requirements
+ * on the field.
+ */
+public class ByteFieldSource extends FieldCacheSource {
+ private FieldCache.ByteParser parser;
+
+ /**
+ * Create a cached byte field source with default string-to-byte parser.
+ */
+ public ByteFieldSource(String field) {
+ this(field, null);
+ }
+
+ /**
+ * Create a cached byte field source with a specific string-to-byte parser.
+ */
+ public ByteFieldSource(String field, FieldCache.ByteParser parser) {
+ super(field);
+ this.parser = parser;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.ValueSource#description() */
+ public String description() {
+ return "byte(" + super.description() + ')';
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#getCachedValues(org.apache.lucene.search.FieldCache, java.lang.String, org.apache.lucene.index.IndexReader) */
+ public DocValues getCachedFieldValues (FieldCache cache, String field, IndexReader reader) throws IOException {
+ final byte[] arr = (parser==null) ?
+ cache.getBytes(reader, field) :
+ cache.getBytes(reader, field, parser);
+ return new DocValues(reader.maxDoc()) {
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#floatVal(int) */
+ public float floatVal(int doc) {
+ return (float) arr[doc];
+ }
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#intVal(int) */
+ public int intVal(int doc) {
+ return arr[doc];
+ }
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#toString(int) */
+ public String toString(int doc) {
+ return description() + '=' + intVal(doc);
+ }
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#getInnerArray() */
+ Object getInnerArray() {
+ return arr;
+ }
+ };
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#cachedFieldSourceEquals(org.apache.lucene.search.function.FieldCacheSource) */
+ public boolean cachedFieldSourceEquals(FieldCacheSource o) {
+ if (o.getClass() != ByteFieldSource.class) {
+ return false;
+ }
+ ByteFieldSource other = (ByteFieldSource)o;
+ return this.parser==null ?
+ other.parser==null :
+ this.parser.getClass() == other.parser.getClass();
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#cachedFieldSourceHashCode() */
+ public int cachedFieldSourceHashCode() {
+ return parser==null ?
+ Byte.class.hashCode() : parser.getClass().hashCode();
+ }
+
+}
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/ByteFieldSource.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java Tue Jun 5 09:29:35 2007
@@ -0,0 +1,344 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.Set;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.ComplexExplanation;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.Searcher;
+import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.Weight;
+import org.apache.lucene.util.ToStringUtils;
+
+/**
+ * Query that sets document score as a programmatic function of (up to) two (sub) scores.
+ * <ol>
+ * <li>the score of its subQuery (any query)</li>
+ * <li>(optional) the score of its ValueSourtceQuery,
+ * for most simple/convineient use case this query would be a
+ * {@link org.apache.lucene.search.function.FieldScoreQuery FieldScoreQuery}</li>
+ * </ol>
+ * Subclasses can modify the computation by overriding {@link #customScore(int, float, float)}.
+ *
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental.
+ * The APIs introduced here might change in the future and will not be
+ * supported anymore in such a case.</font>
+ */
+public class CustomScoreQuery extends Query {
+
+ private Query subQuery;
+ private ValueSourceQuery valSrcQuery; // optional, can be null
+ private boolean strict = false; // if true, valueSource part of query does not take part in weights normalization.
+
+ /**
+ * Create a CustomScoreQuery over input subQuery.
+ * @param subQuery the sub query whose scored is being customed. Must not be null.
+ */
+ public CustomScoreQuery(Query subQuery) {
+ this(subQuery,null);
+ }
+
+ /**
+ * Create a CustomScoreQuery over input subQuery and a {@link ValueSourceQuery}.
+ * @param subQuery the sub query whose score is being customed. Must not be null.
+ * @param valSrcQuery a value source query whose scores are used in the custom score
+ * computation. For most simple/convineient use case this would be a
+ * {@link org.apache.lucene.search.function.FieldScoreQuery FieldScoreQuery}.
+ * This parameter is optional - it can be null.
+ */
+ public CustomScoreQuery(Query subQuery, ValueSourceQuery valSrcQuery) {
+ super();
+ this.subQuery = subQuery;
+ this.valSrcQuery = valSrcQuery;
+ if (subQuery == null) throw new IllegalArgumentException("<subqyery> must not be null!");
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Query#rewrite(org.apache.lucene.index.IndexReader) */
+ public Query rewrite(IndexReader reader) throws IOException {
+ subQuery = subQuery.rewrite(reader);
+ if (valSrcQuery!=null) {
+ valSrcQuery = (ValueSourceQuery) valSrcQuery.rewrite(reader);
+ }
+ return this;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Query#extractTerms(java.util.Set) */
+ public void extractTerms(Set terms) {
+ subQuery.extractTerms(terms);
+ if (valSrcQuery!=null) {
+ valSrcQuery.extractTerms(terms);
+ }
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Query#clone() */
+ public Object clone() {
+ CustomScoreQuery clone = (CustomScoreQuery)super.clone();
+ clone.subQuery = (Query) subQuery.clone();
+ if (valSrcQuery!=null) {
+ clone.valSrcQuery = (ValueSourceQuery) valSrcQuery.clone();
+ }
+ return clone;
+ }
+
+ /* (non-Javadoc) @see org.apache.lucene.search.Query#toString(java.lang.String) */
+ public String toString(String field) {
+ StringBuffer sb = new StringBuffer(name()).append("(");
+ sb.append(subQuery.toString(field));
+ if (valSrcQuery!=null) {
+ sb.append(", ").append(valSrcQuery.toString(field));
+ }
+ sb.append(")");
+ sb.append(strict?" STRICT" : "");
+ return sb.toString() + ToStringUtils.boost(getBoost());
+ }
+
+ /** Returns true if <code>o</code> is equal to this. */
+ public boolean equals(Object o) {
+ if (getClass() != o.getClass()) {
+ return false;
+ }
+ CustomScoreQuery other = (CustomScoreQuery)o;
+ return this.getBoost() == other.getBoost()
+ && this.subQuery.equals(other.subQuery)
+ && (this.valSrcQuery==null ? other.valSrcQuery==null
+ : this.valSrcQuery.equals(other.valSrcQuery));
+ }
+
+ /** Returns a hash code value for this object. */
+ public int hashCode() {
+ int valSrcHash = valSrcQuery==null ? 0 : valSrcQuery.hashCode();
+ return (getClass().hashCode() + subQuery.hashCode() + valSrcHash) ^ Float.floatToIntBits(getBoost());
+ }
+
+ /**
+ * Compute a custom score by the subQuery score and the ValueSourceQuery score.
+ * <p>
+ * Subclasses can override this method to modify the custom score.
+ * <p>
+ * The default computation herein is:
+ * <pre>
+ * ModifiedScore = valSrcScore * subQueryScore.
+ * </pre>
+ *
+ * @param doc id of scored doc.
+ * @param subQueryScore score of that doc by the subQuery.
+ * @param valSrcScore score of that doc by the ValueSourceQuery.
+ * @return custom score.
+ */
+ public float customScore(int doc, float subQueryScore, float valSrcScore) {
+ return valSrcScore * subQueryScore;
+ }
+
+ /**
+ * Explain the custom score.
+ * Whenever overriding {@link #customScore(int, float, float)},
+ * this method should also be overriden to provide the correct explanation
+ * for the part of the custom scoring.
+ * @param doc doc being explained.
+ * @param subQueryExpl explanation for the sub-query part.
+ * @param valSrcExpl explanation for the value source part.
+ * @return an explanation for the custom score
+ */
+ public Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpl) {
+ float valSrcScore = valSrcExpl==null ? 1 : valSrcExpl.getValue();
+ Explanation exp = new Explanation( valSrcScore * subQueryExpl.getValue(), "custom score: product of:");
+ exp.addDetail(subQueryExpl);
+ if (valSrcExpl != null) {
+ exp.addDetail(valSrcExpl);
+ }
+ return exp;
+ }
+ //=========================== W E I G H T ============================
+
+ private class CustomWeight implements Weight {
+ Searcher searcher;
+ Weight subQueryWeight;
+ Weight valSrcWeight; // optional
+ boolean qStrict;
+
+ public CustomWeight(Searcher searcher) throws IOException {
+ this.searcher = searcher;
+ this.subQueryWeight = subQuery.weight(searcher);
+ if (valSrcQuery!=null) {
+ this.valSrcWeight = valSrcQuery.createWeight(searcher);
+ }
+ this.qStrict = strict;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Weight#getQuery() */
+ public Query getQuery() {
+ return CustomScoreQuery.this;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Weight#getValue() */
+ public float getValue() {
+ return getBoost();
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Weight#sumOfSquaredWeights() */
+ public float sumOfSquaredWeights() throws IOException {
+ float sum = subQueryWeight.sumOfSquaredWeights();
+ if (valSrcWeight!=null) {
+ if (qStrict) {
+ valSrcWeight.sumOfSquaredWeights(); // do not include ValueSource part in the query normalization
+ } else {
+ sum += valSrcWeight.sumOfSquaredWeights();
+ }
+ }
+ sum *= getBoost() * getBoost(); // boost each sub-weight
+ return sum ;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Weight#normalize(float) */
+ public void normalize(float norm) {
+ norm *= getBoost(); // incorporate boost
+ subQueryWeight.normalize(norm);
+ if (valSrcWeight!=null) {
+ if (qStrict) {
+ valSrcWeight.normalize(1); // do not normalize the ValueSource part
+ } else {
+ valSrcWeight.normalize(norm);
+ }
+ }
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Weight#scorer(org.apache.lucene.index.IndexReader) */
+ public Scorer scorer(IndexReader reader) throws IOException {
+ Scorer subQueryScorer = subQueryWeight.scorer(reader);
+ Scorer valSrcScorer = (valSrcWeight==null ? null : valSrcWeight.scorer(reader));
+ return new CustomScorer(getSimilarity(searcher), reader, this, subQueryScorer, valSrcScorer);
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Weight#explain(org.apache.lucene.index.IndexReader, int) */
+ public Explanation explain(IndexReader reader, int doc) throws IOException {
+ return scorer(reader).explain(doc);
+ }
+ }
+
+
+ //=========================== S C O R E R ============================
+
+ /**
+ * A scorer that applies a (callback) function on scores of the subQuery.
+ */
+ private class CustomScorer extends Scorer {
+ private final CustomWeight weight;
+ private final float qWeight;
+ private Scorer subQueryScorer;
+ private Scorer valSrcScorer; // optional
+ private IndexReader reader;
+
+ // constructor
+ private CustomScorer(Similarity similarity, IndexReader reader, CustomWeight w,
+ Scorer subQueryScorer, Scorer valSrcScorer) throws IOException {
+ super(similarity);
+ this.weight = w;
+ this.qWeight = w.getValue();
+ this.subQueryScorer = subQueryScorer;
+ this.valSrcScorer = valSrcScorer;
+ this.reader = reader;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Scorer#next() */
+ public boolean next() throws IOException {
+ boolean hasNext = subQueryScorer.next();
+ if (valSrcScorer!=null && hasNext) {
+ valSrcScorer.skipTo(subQueryScorer.doc());
+ }
+ return hasNext;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Scorer#doc() */
+ public int doc() {
+ return subQueryScorer.doc();
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Scorer#score() */
+ public float score() throws IOException {
+ float valSrcScore = (valSrcScorer==null ? 1 : valSrcScorer.score());
+ return qWeight * customScore(subQueryScorer.doc(), subQueryScorer.score(), valSrcScore);
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Scorer#skipTo(int) */
+ public boolean skipTo(int target) throws IOException {
+ boolean hasNext = subQueryScorer.skipTo(target);
+ if (valSrcScorer!=null && hasNext) {
+ valSrcScorer.skipTo(subQueryScorer.doc());
+ }
+ return hasNext;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Scorer#explain(int) */
+ public Explanation explain(int doc) throws IOException {
+ Explanation subQueryExpl = weight.subQueryWeight.explain(reader,doc);
+ if (!subQueryExpl.isMatch()) {
+ return subQueryExpl;
+ }
+ // match
+ Explanation valSrcExpl = valSrcScorer==null ? null : valSrcScorer.explain(doc);
+ Explanation customExp = customExplain(doc,subQueryExpl,valSrcExpl);
+ float sc = qWeight * customExp.getValue();
+ Explanation res = new ComplexExplanation(
+ true, sc, CustomScoreQuery.this.toString() + ", product of:");
+ res.addDetail(customExp);
+ res.addDetail(new Explanation(qWeight, "queryBoost")); // actually using the q boost as q weight (== weight value)
+ return res;
+ }
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Query#createWeight(org.apache.lucene.search.Searcher) */
+ protected Weight createWeight(Searcher searcher) throws IOException {
+ return new CustomWeight(searcher);
+ }
+
+ /**
+ * Checks if this is strict custom scoring.
+ * In strict custom scoring, the ValueSource part of does not participate in weight normalization.
+ * This may be useful when one wants full control over how scores are modified, and does
+ * not care about normalizing by the ValueSource part.
+ * One particular case where this is useful if for testing this query.
+ * <P>
+ * Note: only has effect when the ValueSource part is not null.
+ */
+ public boolean isStrict() {
+ return strict;
+ }
+
+ /**
+ * Set the strict mode of this query.
+ * @param strict The strict mode to set.
+ * @see #isStrict()
+ */
+ public void setStrict(boolean strict) {
+ this.strict = strict;
+ }
+
+ /**
+ * A short name of this query, used in {@link #toString(String)}.
+ */
+ public String name() {
+ return "custom";
+ }
+
+}
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/CustomScoreQuery.java
------------------------------------------------------------------------------
svn:executable = *
Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java Tue Jun 5 09:29:35 2007
@@ -0,0 +1,176 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.search.Explanation;
+
+/**
+ * Expert: represents field values as different types.
+ * Normally created via a
+ * {@link org.apache.lucene.search.function.ValueSource ValueSuorce}
+ * for a particular field and reader.
+ *
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental.
+ * The APIs introduced here might change in the future and will not be
+ * supported anymore in such a case.</font>
+ *
+ * @author yonik
+ */
+public abstract class DocValues {
+ /*
+ * DocValues is distinct from ValueSource because
+ * there needs to be an object created at query evaluation time that
+ * is not referenced by the query itself because:
+ * - Query objects should be MT safe
+ * - For caching, Query objects are often used as keys... you don't
+ * want the Query carrying around big objects
+ */
+
+ private int nVals;
+
+ /**
+ * Constructor with input number of values(docs).
+ * @param nVals
+ */
+ public DocValues (int nVals) {
+ this.nVals = nVals;
+ }
+
+ // prevent using this constructor
+ private DocValues () {
+
+ }
+ /**
+ * Return doc value as a float.
+ * <P>Mandatory: every DocValues implementation must implement at least this method.
+ * @param doc document whose float value is requested.
+ */
+ public abstract float floatVal(int doc);
+
+ /**
+ * Return doc value as an int.
+ * <P>Optional: DocValues implementation can (but don't have to) override this method.
+ * @param doc document whose int value is requested.
+ */
+ public int intVal(int doc) {
+ return (int) floatVal(doc);
+ }
+
+ /**
+ * Return doc value as a long.
+ * <P>Optional: DocValues implementation can (but don't have to) override this method.
+ * @param doc document whose long value is requested.
+ */
+ public long longVal(int doc) {
+ return (long) floatVal(doc);
+ }
+
+ /**
+ * Return doc value as a double.
+ * <P>Optional: DocValues implementation can (but don't have to) override this method.
+ * @param doc document whose double value is requested.
+ */
+ public double doubleVal(int doc) {
+ return (double) floatVal(doc);
+ }
+
+ /**
+ * Return doc value as a string.
+ * <P>Optional: DocValues implementation can (but don't have to) override this method.
+ * @param doc document whose string value is requested.
+ */
+ public String strVal(int doc) {
+ return Float.toString(floatVal(doc));
+ }
+
+ /**
+ * Return a string representation of a doc value, as reuired for Explanations.
+ */
+ public abstract String toString(int doc);
+
+ /**
+ * Explain the scoring value for the input doc.
+ */
+ public Explanation explain(int doc) {
+ return new Explanation(floatVal(doc), toString(doc));
+ }
+
+ /**
+ * Expert: for test purposes only, return the inner array of values, or null if not applicable.
+ * <p>
+ * Allows tests to verify that loaded values are:
+ * <ol>
+ * <li>indeed cached/reused.</li>
+ * <li>stored in the expected size/type (byte/short/int/float).</li>
+ * </ol>
+ * Note: Tested implementations of DocValues must override this method for the test to pass!
+ */
+ Object getInnerArray() {
+ return new Object[0];
+ }
+
+ // --- some simple statistics on values
+ private float minVal;
+ private float maxVal;
+ private float avgVal;
+ private boolean computed=false;
+ // compute optional values
+ private void compute () {
+ if (computed) {
+ return;
+ }
+ minVal = Float.MAX_VALUE;
+ maxVal = 0;
+ float sum = 0;
+ for (int i=0; i<nVals; i++) {
+ float val = floatVal(i);
+ sum += val;
+ minVal = Math.min(minVal,val);
+ maxVal = Math.max(maxVal,val);
+ }
+ avgVal = sum / nVals;
+ computed = true;
+ }
+ /**
+ * Optional op.
+ * Returns the minimum of all values.
+ */
+ public float getMinValue () {
+ compute();
+ return minVal;
+ }
+
+ /**
+ * Optional op.
+ * Returns the maximum of all values.
+ */
+ public float getMaxValue () {
+ compute();
+ return maxVal;
+ }
+
+ /**
+ * Returns the average of all values.
+ */
+ public float getAverageValue () {
+ compute();
+ return avgVal;
+ }
+
+}
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/DocValues.java
------------------------------------------------------------------------------
svn:executable = *
Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldCacheSource.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldCacheSource.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldCacheSource.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldCacheSource.java Tue Jun 5 09:29:35 2007
@@ -0,0 +1,105 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.FieldCache;
+
+/**
+ * Expert: A base class for ValueSource implementations that retrieve values for
+ * a single field from the {@link org.apache.lucene.search.FieldCache FieldCache}.
+ * <p>
+ * Fields used herein nust be indexed (doesn't matter if these fields are stored or not).
+ * <p>
+ * It is assumed that each such indexed field is untokenized, or at least has a single token in a document.
+ * For documents with multiple tokens of the same field, behavior is undefined (It is likely that current
+ * code would use the value of one of these tokens, but this is not guaranteed).
+ * <p>
+ * Document with no tokens in this field are assigned the <code>Zero</code> value.
+ *
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental.
+ * The APIs introduced here might change in the future and will not be
+ * supported anymore in such a case.</font>
+ *
+ * @author yonik
+ */
+public abstract class FieldCacheSource extends ValueSource {
+ private String field;
+ private FieldCache cache = FieldCache.DEFAULT;
+
+ /**
+ * Create a cached field source for the input field.
+ */
+ public FieldCacheSource(String field) {
+ this.field=field;
+ }
+
+ /* (non-Javadoc) @see org.apache.lucene.search.function.ValueSource#getValues(org.apache.lucene.index.IndexReader) */
+ public final DocValues getValues(IndexReader reader) throws IOException {
+ return getCachedFieldValues(cache, field, reader);
+ }
+
+ /* (non-Javadoc) @see org.apache.lucene.search.function.ValueSource#description() */
+ public String description() {
+ return field;
+ }
+
+ /**
+ * Return cached DocValues for input field and reader.
+ * @param cache FieldCache so that values of a field are loaded once per reader (RAM allowing)
+ * @param field Field for which values are required.
+ * @see ValueSource
+ */
+ public abstract DocValues getCachedFieldValues(FieldCache cache, String field, IndexReader reader) throws IOException;
+
+ /*(non-Javadoc) @see java.lang.Object#equals(java.lang.Object) */
+ public final boolean equals(Object o) {
+ if (!(o instanceof FieldCacheSource)) {
+ return false;
+ }
+ FieldCacheSource other = (FieldCacheSource) o;
+ return
+ this.cache == other.cache &&
+ this.field.equals(other.field) &&
+ cachedFieldSourceEquals(other);
+ }
+
+ /*(non-Javadoc) @see java.lang.Object#hashCode() */
+ public final int hashCode() {
+ return
+ cache.hashCode() +
+ field.hashCode() +
+ cachedFieldSourceHashCode();
+ }
+
+ /**
+ * Check if equals to another {@link FieldCacheSource}, already knowing that cache and field are equal.
+ * @see Object#equals(java.lang.Object)
+ */
+ public abstract boolean cachedFieldSourceEquals(FieldCacheSource other);
+
+ /**
+ * Return a hash code of a {@link FieldCacheSource}, without the hash-codes of the field
+ * and the cache (those are taken care of elsewhere).
+ * @see Object#hashCode()
+ */
+ public abstract int cachedFieldSourceHashCode();
+}
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldCacheSource.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldScoreQuery.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldScoreQuery.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldScoreQuery.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldScoreQuery.java Tue Jun 5 09:29:35 2007
@@ -0,0 +1,127 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+/**
+ * A query that scores each document as the value of the numeric input field.
+ * <p>
+ * The query matches all documents, and scores each document according to the numeric
+ * value of that field.
+ * <p>
+ * It is assumed, and expected, that:
+ * <ul>
+ * <li>The field used here is indexed, and has exactly
+ * one token in every scored document.</li>
+ * <li>Best if this field is un_tokenized.</li>
+ * <li>That token is parsable to the selected type.</li>
+ * </ul>
+ * <p>
+ * Combining this query in a FunctionQuery allows much freedom in affecting document scores.
+ * Note, that with this freedom comes responsibility: it is more than likely that the
+ * default Lucene scoring is superior in quality to scoring modified as explained here.
+ * However, in some cases, and certainly for research experiments, this capability may turn useful.
+ * <p>
+ * When contructing this query, select the appropriate type. That type should match the data stored in the
+ * field. So in fact the "right" type should be selected before indexing. Type selection
+ * has effect on the RAM usage:
+ * <ul>
+ * <li>{@link Type#BYTE} consumes 1 * maxDocs bytes.</li>
+ * <li>{@link Type#SHORT} consumes 2 * maxDocs bytes.</li>
+ * <li>{@link Type#INT} consumes 4 * maxDocs bytes.</li>
+ * <li>{@link Type#FLOAT} consumes 8 * maxDocs bytes.</li>
+ * </ul>
+ * <p>
+ * <b>Caching:</b>
+ * Values for the numeric field are loaded once and cached in memory for further use with the same IndexReader.
+ * To take advantage of this, it is extremely important to reuse index-readers or index-searchers,
+ * otherwise, for instance if for each query a new index reader is opened, large penalties would be
+ * payd for loading the field values into memory over and over again!
+ *
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental.
+ * The APIs introduced here might change in the future and will not be
+ * supported anymore in such a case.</font>
+ */
+public class FieldScoreQuery extends ValueSourceQuery {
+
+ /**
+ * Type of score field, indicating how field values are interpreted/parsed.
+ * <p>
+ * The type selected at search search time should match the data stored in the field.
+ * Different types have different RAM requirements:
+ * <ul>
+ * <li>{@link #BYTE} consumes 1 * maxDocs bytes.</li>
+ * <li>{@link #SHORT} consumes 2 * maxDocs bytes.</li>
+ * <li>{@link #INT} consumes 4 * maxDocs bytes.</li>
+ * <li>{@link #FLOAT} consumes 8 * maxDocs bytes.</li>
+ * </ul>
+ */
+ public static class Type {
+
+ /** field values are interpreted as numeric byte values. */
+ public static final Type BYTE = new Type("byte");
+
+ /** field values are interpreted as numeric short values. */
+ public static final Type SHORT = new Type("short");
+
+ /** field values are interpreted as numeric int values. */
+ public static final Type INT = new Type("int");
+
+ /** field values are interpreted as numeric float values. */
+ public static final Type FLOAT = new Type("float");
+
+ private String typeName;
+ private Type (String name) {
+ this.typeName = name;
+ }
+ /*(non-Javadoc) @see java.lang.Object#toString() */
+ public String toString() {
+ return getClass().getName()+"::"+typeName;
+ }
+ }
+
+ /**
+ * Create a FieldScoreQuery - a query that scores each document as the value of the numeric input field.
+ * <p>
+ * The <code>type</code> param tells how to parse the field string values into a numeric score value.
+ * @param field the numeric field to be used.
+ * @param type the type of the field: either
+ * {@link Type#BYTE}, {@link Type#SHORT}, {@link Type#INT}, or {@link Type#FLOAT}.
+ */
+ public FieldScoreQuery(String field, Type type) {
+ super(getValueSource(field,type));
+ }
+
+ // create the appropriate (cached) field value source.
+ private static ValueSource getValueSource(String field, Type type) {
+ if (type == Type.BYTE) {
+ return new ByteFieldSource(field);
+ }
+ if (type == Type.SHORT) {
+ return new ShortFieldSource(field);
+ }
+ if (type == Type.INT) {
+ return new IntFieldSource(field);
+ }
+ if (type == Type.FLOAT) {
+ return new FloatFieldSource(field);
+ }
+ throw new IllegalArgumentException(type+" is not a known Field Score Query Type!");
+ }
+
+}
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldScoreQuery.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/FieldScoreQuery.java
------------------------------------------------------------------------------
svn:executable = *
Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/FloatFieldSource.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/FloatFieldSource.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/FloatFieldSource.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/FloatFieldSource.java Tue Jun 5 09:29:35 2007
@@ -0,0 +1,102 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.FieldCache;
+import org.apache.lucene.search.function.DocValues;
+
+import java.io.IOException;
+
+/**
+ * Expert: obtains float field values from the
+ * {@link org.apache.lucene.search.FieldCache FieldCache}
+ * using <code>getFloats()</code> and makes those values
+ * available as other numeric types, casting as needed.
+ *
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental.
+ * The APIs introduced here might change in the future and will not be
+ * supported anymore in such a case.</font>
+ *
+ * @see org.apache.lucene.search.function.FieldCacheSource for requirements
+ * on the field.
+ *
+ * @author yonik
+ */
+public class FloatFieldSource extends FieldCacheSource {
+ private FieldCache.FloatParser parser;
+
+ /**
+ * Create a cached float field source with default string-to-float parser.
+ */
+ public FloatFieldSource(String field) {
+ this(field, null);
+ }
+
+ /**
+ * Create a cached float field source with a specific string-to-float parser.
+ */
+ public FloatFieldSource(String field, FieldCache.FloatParser parser) {
+ super(field);
+ this.parser = parser;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.ValueSource#description() */
+ public String description() {
+ return "float(" + super.description() + ')';
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#getCachedValues(org.apache.lucene.search.FieldCache, java.lang.String, org.apache.lucene.index.IndexReader) */
+ public DocValues getCachedFieldValues (FieldCache cache, String field, IndexReader reader) throws IOException {
+ final float[] arr = (parser==null) ?
+ cache.getFloats(reader, field) :
+ cache.getFloats(reader, field, parser);
+ return new DocValues(reader.maxDoc()) {
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#floatVal(int) */
+ public float floatVal(int doc) {
+ return arr[doc];
+ }
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#toString(int) */
+ public String toString(int doc) {
+ return description() + '=' + arr[doc];
+ }
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#getInnerArray() */
+ Object getInnerArray() {
+ return arr;
+ }
+ };
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#cachedFieldSourceEquals(org.apache.lucene.search.function.FieldCacheSource) */
+ public boolean cachedFieldSourceEquals(FieldCacheSource o) {
+ if (o.getClass() != FloatFieldSource.class) {
+ return false;
+ }
+ FloatFieldSource other = (FloatFieldSource)o;
+ return this.parser==null ?
+ other.parser==null :
+ this.parser.getClass() == other.parser.getClass();
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#cachedFieldSourceHashCode() */
+ public int cachedFieldSourceHashCode() {
+ return parser==null ?
+ Float.class.hashCode() : parser.getClass().hashCode();
+ }
+}
\ No newline at end of file
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/FloatFieldSource.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/IntFieldSource.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/IntFieldSource.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/IntFieldSource.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/IntFieldSource.java Tue Jun 5 09:29:35 2007
@@ -0,0 +1,107 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.FieldCache;
+import org.apache.lucene.search.function.DocValues;
+
+import java.io.IOException;
+
+/**
+ * Expert: obtains int field values from the
+ * {@link org.apache.lucene.search.FieldCache FieldCache}
+ * using <code>getInts()</code> and makes those values
+ * available as other numeric types, casting as needed.
+ *
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental.
+ * The APIs introduced here might change in the future and will not be
+ * supported anymore in such a case.</font>
+ *
+ * @see org.apache.lucene.search.function.FieldCacheSource for requirements
+ * on the field.
+ *
+ * @author yonik
+ */
+public class IntFieldSource extends FieldCacheSource {
+ private FieldCache.IntParser parser;
+
+ /**
+ * Create a cached int field source with default string-to-int parser.
+ */
+ public IntFieldSource(String field) {
+ this(field, null);
+ }
+
+ /**
+ * Create a cached int field source with a specific string-to-int parser.
+ */
+ public IntFieldSource(String field, FieldCache.IntParser parser) {
+ super(field);
+ this.parser = parser;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.ValueSource#description() */
+ public String description() {
+ return "int(" + super.description() + ')';
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#getCachedValues(org.apache.lucene.search.FieldCache, java.lang.String, org.apache.lucene.index.IndexReader) */
+ public DocValues getCachedFieldValues (FieldCache cache, String field, IndexReader reader) throws IOException {
+ final int[] arr = (parser==null) ?
+ cache.getInts(reader, field) :
+ cache.getInts(reader, field, parser);
+ return new DocValues(reader.maxDoc()) {
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#floatVal(int) */
+ public float floatVal(int doc) {
+ return (float) arr[doc];
+ }
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#intVal(int) */
+ public int intVal(int doc) {
+ return arr[doc];
+ }
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#toString(int) */
+ public String toString(int doc) {
+ return description() + '=' + intVal(doc);
+ }
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#getInnerArray() */
+ Object getInnerArray() {
+ return arr;
+ }
+ };
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#cachedFieldSourceEquals(org.apache.lucene.search.function.FieldCacheSource) */
+ public boolean cachedFieldSourceEquals(FieldCacheSource o) {
+ if (o.getClass() != IntFieldSource.class) {
+ return false;
+ }
+ IntFieldSource other = (IntFieldSource)o;
+ return this.parser==null ?
+ other.parser==null :
+ this.parser.getClass() == other.parser.getClass();
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#cachedFieldSourceHashCode() */
+ public int cachedFieldSourceHashCode() {
+ return parser==null ?
+ Integer.class.hashCode() : parser.getClass().hashCode();
+ }
+
+}
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/IntFieldSource.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/IntFieldSource.java
------------------------------------------------------------------------------
svn:executable = *
Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/OrdFieldSource.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/OrdFieldSource.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/OrdFieldSource.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/OrdFieldSource.java Tue Jun 5 09:29:35 2007
@@ -0,0 +1,103 @@
+/**
+ * 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.search.function;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.FieldCache;
+
+import java.io.IOException;
+
+/**
+ * Expert: obtains the ordinal of the field value from the default Lucene
+ * {@link org.apache.lucene.search.FieldCache Fieldcache} using getStringIndex().
+ * <p>
+ * The native lucene index order is used to assign an ordinal value for each field value.
+ * <p
+ * Field values (terms) are lexicographically ordered by unicode value, and numbered starting at 1.
+ * <p>
+ * Example:
+ * <br>If there were only three field values: "apple","banana","pear"
+ * <br>then ord("apple")=1, ord("banana")=2, ord("pear")=3
+ * <p>
+ * WARNING:
+ * ord() depends on the position in an index and can thus change
+ * when other documents are inserted or deleted,
+ * or if a MultiSearcher is used.
+ *
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental.
+ * The APIs introduced here might change in the future and will not be
+ * supported anymore in such a case.</font>
+ *
+ * @author yonik
+ */
+
+public class OrdFieldSource extends ValueSource {
+ protected String field;
+
+ /**
+ * Contructor for a certain field.
+ * @param field field whose values order is used.
+ */
+ public OrdFieldSource(String field) {
+ this.field = field;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.ValueSource#description() */
+ public String description() {
+ return "ord(" + field + ')';
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.ValueSource#getValues(org.apache.lucene.index.IndexReader) */
+ public DocValues getValues(IndexReader reader) throws IOException {
+ final int[] arr = FieldCache.DEFAULT.getStringIndex(reader, field).order;
+ return new DocValues(arr.length) {
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#floatVal(int) */
+ public float floatVal(int doc) {
+ return (float)arr[doc];
+ }
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#strVal(int) */
+ public String strVal(int doc) {
+ // the string value of the ordinal, not the string itself
+ return Integer.toString(arr[doc]);
+ }
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#toString(int) */
+ public String toString(int doc) {
+ return description() + '=' + intVal(doc);
+ }
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#getInnerArray() */
+ Object getInnerArray() {
+ return arr;
+ }
+ };
+ }
+
+ /*(non-Javadoc) @see java.lang.Object#equals(java.lang.Object) */
+ public boolean equals(Object o) {
+ if (o.getClass() != OrdFieldSource.class) return false;
+ OrdFieldSource other = (OrdFieldSource)o;
+ return this.field.equals(other.field);
+ }
+
+ private static final int hcode = OrdFieldSource.class.hashCode();
+
+ /*(non-Javadoc) @see java.lang.Object#hashCode() */
+ public int hashCode() {
+ return hcode + field.hashCode();
+ }
+}
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/OrdFieldSource.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/ReverseOrdFieldSource.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/ReverseOrdFieldSource.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/ReverseOrdFieldSource.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/ReverseOrdFieldSource.java Tue Jun 5 09:29:35 2007
@@ -0,0 +1,112 @@
+/**
+ * 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.search.function;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.FieldCache;
+
+import java.io.IOException;
+
+/**
+ * Expert: obtains the ordinal of the field value from the default Lucene
+ * {@link org.apache.lucene.search.FieldCache FieldCache} using getStringIndex()
+ * and reverses the order.
+ * <p>
+ * The native lucene index order is used to assign an ordinal value for each field value.
+ * <p>
+ * Field values (terms) are lexicographically ordered by unicode value, and numbered starting at 1.
+ * <br>
+ * Example of reverse ordinal (rord):
+ * <br>If there were only three field values: "apple","banana","pear"
+ * <br>then rord("apple")=3, rord("banana")=2, ord("pear")=1
+ * <p>
+ * WARNING:
+ * rord() depends on the position in an index and can thus change
+ * when other documents are inserted or deleted,
+ * or if a MultiSearcher is used.
+ *
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental.
+ * The APIs introduced here might change in the future and will not be
+ * supported anymore in such a case.</font>
+ *
+ * @author yonik
+ */
+
+public class ReverseOrdFieldSource extends ValueSource {
+ public String field;
+
+ /**
+ * Contructor for a certain field.
+ * @param field field whose values reverse order is used.
+ */
+ public ReverseOrdFieldSource(String field) {
+ this.field = field;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.ValueSource#description() */
+ public String description() {
+ return "rord("+field+')';
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.ValueSource#getValues(org.apache.lucene.index.IndexReader) */
+ public DocValues getValues(IndexReader reader) throws IOException {
+ final FieldCache.StringIndex sindex = FieldCache.DEFAULT.getStringIndex(reader, field);
+
+ final int arr[] = sindex.order;
+ final int end = sindex.lookup.length;
+
+ return new DocValues(arr.length) {
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#floatVal(int) */
+ public float floatVal(int doc) {
+ return (float)(end - arr[doc]);
+ }
+ /* (non-Javadoc) @see org.apache.lucene.search.function.DocValues#intVal(int) */
+ public int intVal(int doc) {
+ return end - arr[doc];
+ }
+ /* (non-Javadoc) @see org.apache.lucene.search.function.DocValues#strVal(int) */
+ public String strVal(int doc) {
+ // the string value of the ordinal, not the string itself
+ return Integer.toString(intVal(doc));
+ }
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#toString(int) */
+ public String toString(int doc) {
+ return description() + '=' + strVal(doc);
+ }
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#getInnerArray() */
+ Object getInnerArray() {
+ return arr;
+ }
+ };
+ }
+
+ /*(non-Javadoc) @see java.lang.Object#equals(java.lang.Object) */
+ public boolean equals(Object o) {
+ if (o.getClass() != ReverseOrdFieldSource.class) return false;
+ ReverseOrdFieldSource other = (ReverseOrdFieldSource)o;
+ return this.field.equals(other.field);
+ }
+
+ private static final int hcode = ReverseOrdFieldSource.class.hashCode();
+
+ /*(non-Javadoc) @see java.lang.Object#hashCode() */
+ public int hashCode() {
+ return hcode + field.hashCode();
+ }
+}
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/ReverseOrdFieldSource.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/ShortFieldSource.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/ShortFieldSource.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/ShortFieldSource.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/ShortFieldSource.java Tue Jun 5 09:29:35 2007
@@ -0,0 +1,105 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.FieldCache;
+import org.apache.lucene.search.function.DocValues;
+
+import java.io.IOException;
+
+/**
+ * Expert: obtains short field values from the
+ * {@link org.apache.lucene.search.FieldCache FieldCache}
+ * using <code>getShorts()</code> and makes those values
+ * available as other numeric types, casting as needed.
+ *
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental.
+ * The APIs introduced here might change in the future and will not be
+ * supported anymore in such a case.</font>
+ *
+ * @see org.apache.lucene.search.function.FieldCacheSource for requirements
+ * on the field.
+ */
+public class ShortFieldSource extends FieldCacheSource {
+ private FieldCache.ShortParser parser;
+
+ /**
+ * Create a cached short field source with default string-to-short parser.
+ */
+ public ShortFieldSource(String field) {
+ this(field, null);
+ }
+
+ /**
+ * Create a cached short field source with a specific string-to-short parser.
+ */
+ public ShortFieldSource(String field, FieldCache.ShortParser parser) {
+ super(field);
+ this.parser = parser;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.ValueSource#description() */
+ public String description() {
+ return "short(" + super.description() + ')';
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#getCachedValues(org.apache.lucene.search.FieldCache, java.lang.String, org.apache.lucene.index.IndexReader) */
+ public DocValues getCachedFieldValues (FieldCache cache, String field, IndexReader reader) throws IOException {
+ final short[] arr = (parser==null) ?
+ cache.getShorts(reader, field) :
+ cache.getShorts(reader, field, parser);
+ return new DocValues(reader.maxDoc()) {
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#floatVal(int) */
+ public float floatVal(int doc) {
+ return (float) arr[doc];
+ }
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#intVal(int) */
+ public int intVal(int doc) {
+ return arr[doc];
+ }
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#toString(int) */
+ public String toString(int doc) {
+ return description() + '=' + intVal(doc);
+ }
+ /*(non-Javadoc) @see org.apache.lucene.search.function.DocValues#getInnerArray() */
+ Object getInnerArray() {
+ return arr;
+ }
+ };
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#cachedFieldSourceEquals(org.apache.lucene.search.function.FieldCacheSource) */
+ public boolean cachedFieldSourceEquals(FieldCacheSource o) {
+ if (o.getClass() != ShortFieldSource.class) {
+ return false;
+ }
+ ShortFieldSource other = (ShortFieldSource)o;
+ return this.parser==null ?
+ other.parser==null :
+ this.parser.getClass() == other.parser.getClass();
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.function.FieldCacheSource#cachedFieldSourceHashCode() */
+ public int cachedFieldSourceHashCode() {
+ return parser==null ?
+ Short.class.hashCode() : parser.getClass().hashCode();
+ }
+
+}
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/ShortFieldSource.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSource.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSource.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSource.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSource.java Tue Jun 5 09:29:35 2007
@@ -0,0 +1,74 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.function.DocValues;
+import org.apache.lucene.util.ToStringUtils;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+/**
+ * Expert: source of values for basic function queries.
+ * <P>At its default/simplest form, values - one per doc - are used as the score of that doc.
+ * <P>Values are instantiated as
+ * {@link org.apache.lucene.search.function.DocValues DocValues} for a particular reader.
+ * <P>ValueSource implementations differ in RAM requirements: it would always be a factor
+ * of the number of documents, but for each document the number of bytes can be 1, 2, 4, or 8.
+ *
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental.
+ * The APIs introduced here might change in the future and will not be
+ * supported anymore in such a case.</font>
+ *
+ * @author yonik
+ */
+public abstract class ValueSource implements Serializable {
+
+ /**
+ * Return the DocValues used by the function query.
+ * @param reader the IndexReader used to read these values.
+ * If any caching is involved, that caching would also be IndexReader based.
+ * @throws IOException for any error.
+ */
+ public abstract DocValues getValues(IndexReader reader) throws IOException;
+
+ /**
+ * description of field, used in explain()
+ */
+ public abstract String description();
+
+ /* (non-Javadoc) @see java.lang.Object#toString() */
+ public String toString() {
+ return description();
+ }
+
+ /**
+ * Needed for possible caching of query results - used by {@link ValueSourceQuery#equals(Object)}.
+ * @see Object#equals(Object)
+ */
+ public abstract boolean equals(Object o);
+
+ /**
+ * Needed for possible caching of query results - used by {@link ValueSourceQuery#hashCode()}.
+ * @see Object#hashCode()
+ */
+ public abstract int hashCode();
+
+}
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSource.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSource.java
------------------------------------------------------------------------------
svn:executable = *
Added: lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSourceQuery.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSourceQuery.java?view=auto&rev=544546
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSourceQuery.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSourceQuery.java Tue Jun 5 09:29:35 2007
@@ -0,0 +1,201 @@
+package org.apache.lucene.search.function;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.*;
+import org.apache.lucene.util.ToStringUtils;
+
+import java.io.IOException;
+import java.util.Set;
+
+/**
+ * Expert: A Query that sets the scores of document to the
+ * values obtained from a {@link org.apache.lucene.search.function.ValueSource ValueSource}.
+ * <p>
+ * The value source can be based on a (cached) value of an indexd field, but it
+ * can also be based on an external source, e.g. values read from an external database.
+ * <p>
+ * Score is set as: Score(doc,query) = query.getBoost()<sup>2</sup> * valueSource(doc).
+ *
+ * <p><font color="#FF0000">
+ * WARNING: The status of the <b>search.function</b> package is experimental.
+ * The APIs introduced here might change in the future and will not be
+ * supported anymore in such a case.</font>
+ *
+ * @author yonik
+ */
+public class ValueSourceQuery extends Query {
+ ValueSource valSrc;
+
+ /**
+ * Create a value source query
+ * @param valSrc provides the values defines the function to be used for scoring
+ */
+ public ValueSourceQuery(ValueSource valSrc) {
+ this.valSrc=valSrc;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Query#rewrite(org.apache.lucene.index.IndexReader) */
+ public Query rewrite(IndexReader reader) throws IOException {
+ return this;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Query#extractTerms(java.util.Set) */
+ public void extractTerms(Set terms) {
+ // no terms involved here
+ }
+
+ private class ValueSourceWeight implements Weight {
+ Searcher searcher;
+ float queryNorm;
+ float queryWeight;
+
+ public ValueSourceWeight(Searcher searcher) {
+ this.searcher = searcher;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Weight#getQuery() */
+ public Query getQuery() {
+ return ValueSourceQuery.this;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Weight#getValue() */
+ public float getValue() {
+ return queryWeight;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Weight#sumOfSquaredWeights() */
+ public float sumOfSquaredWeights() throws IOException {
+ queryWeight = getBoost();
+ return queryWeight * queryWeight;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Weight#normalize(float) */
+ public void normalize(float norm) {
+ this.queryNorm = norm;
+ queryWeight *= this.queryNorm;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Weight#scorer(org.apache.lucene.index.IndexReader) */
+ public Scorer scorer(IndexReader reader) throws IOException {
+ return new ValueSourceScorer(getSimilarity(searcher), reader, this);
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Weight#explain(org.apache.lucene.index.IndexReader, int) */
+ public Explanation explain(IndexReader reader, int doc) throws IOException {
+ return scorer(reader).explain(doc);
+ }
+ }
+
+ /**
+ * A scorer that (simply) matches all documents, and scores each document with
+ * the value of the value soure in effect. As an example, if the value source
+ * is a (cached) field source, then value of that field in that document will
+ * be used. (assuming field is indexed for this doc, with a single token.)
+ */
+ private class ValueSourceScorer extends Scorer {
+ private final IndexReader reader;
+ private final ValueSourceWeight weight;
+ private final int maxDoc;
+ private final float qWeight;
+ private int doc=-1;
+ private final DocValues vals;
+
+ // constructor
+ private ValueSourceScorer(Similarity similarity, IndexReader reader, ValueSourceWeight w) throws IOException {
+ super(similarity);
+ this.weight = w;
+ this.qWeight = w.getValue();
+ this.reader = reader;
+ this.maxDoc = reader.maxDoc();
+ // this is when/where the values are first created.
+ vals = valSrc.getValues(reader);
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Scorer#next() */
+ public boolean next() throws IOException {
+ for(;;) {
+ ++doc;
+ if (doc>=maxDoc) {
+ return false;
+ }
+ if (reader.isDeleted(doc)) {
+ continue;
+ }
+ return true;
+ }
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Scorer#doc()
+ */
+ public int doc() {
+ return doc;
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Scorer#score() */
+ public float score() throws IOException {
+ return qWeight * vals.floatVal(doc);
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Scorer#skipTo(int) */
+ public boolean skipTo(int target) throws IOException {
+ doc=target-1;
+ return next();
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Scorer#explain(int) */
+ public Explanation explain(int doc) throws IOException {
+ float sc = qWeight * vals.floatVal(doc);
+
+ Explanation result = new ComplexExplanation(
+ true, sc, ValueSourceQuery.this.toString() + ", product of:");
+
+ result.addDetail(vals.explain(doc));
+ result.addDetail(new Explanation(getBoost(), "boost"));
+ result.addDetail(new Explanation(weight.queryNorm,"queryNorm"));
+ return result;
+ }
+ }
+
+ /*(non-Javadoc) @see org.apache.lucene.search.Query#createWeight(org.apache.lucene.search.Searcher) */
+ protected Weight createWeight(Searcher searcher) {
+ return new ValueSourceQuery.ValueSourceWeight(searcher);
+ }
+
+ /* (non-Javadoc) @see org.apache.lucene.search.Query#toString(java.lang.String) */
+ public String toString(String field) {
+ return valSrc.toString() + ToStringUtils.boost(getBoost());
+ }
+
+ /** Returns true if <code>o</code> is equal to this. */
+ public boolean equals(Object o) {
+ if (getClass() != o.getClass()) {
+ return false;
+ }
+ ValueSourceQuery other = (ValueSourceQuery)o;
+ return this.getBoost() == other.getBoost()
+ && this.valSrc.equals(other.valSrc);
+ }
+
+ /** Returns a hash code value for this object. */
+ public int hashCode() {
+ return (getClass().hashCode() + valSrc.hashCode()) ^ Float.floatToIntBits(getBoost());
+ }
+
+}
Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/function/ValueSourceQuery.java
------------------------------------------------------------------------------
svn:eol-style = native