/* * Copyright 2004-2009 the original author or authors. * * Licensed 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.compass.core.lucene.engine.all; import java.io.IOException; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.Term; import org.apache.lucene.index.TermPositions; import org.apache.lucene.search.Explanation; 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.search.payloads.BoostingTermQuery; import org.apache.lucene.search.spans.SpanScorer; import org.apache.lucene.search.spans.SpanTermQuery; import org.apache.lucene.search.spans.SpanWeight; import org.apache.lucene.search.spans.TermSpans; /** * A term query that takes into account the All boosting support for specific terms when searching on the * all field. * * @author kimchy * @see BoostingTermQuery */ // LUCENE MONITOR public class AllBoostingTermQuery extends SpanTermQuery { public AllBoostingTermQuery(Term term) { super(term); } protected Weight createWeight(Searcher searcher) throws IOException { return new AllBoostingTermWeight(this, searcher); } protected class AllBoostingTermWeight extends SpanWeight implements Weight { public AllBoostingTermWeight(AllBoostingTermQuery query, Searcher searcher) throws IOException { super(query, searcher); } public Scorer scorer(IndexReader reader) throws IOException { return new BoostingSpanScorer((TermSpans) query.getSpans(reader), this, similarity, reader.norms(query.getField())); } class BoostingSpanScorer extends SpanScorer { //TODO: is this the best way to allocate this? byte[] payload = new byte[4]; private TermPositions positions; protected float payloadScore; private int payloadsSeen; public BoostingSpanScorer(TermSpans spans, Weight weight, Similarity similarity, byte[] norms) throws IOException { super(spans, weight, similarity, norms); positions = spans.getPositions(); } protected boolean setFreqCurrentDoc() throws IOException { if (!more) { return false; } doc = spans.doc(); freq = 0.0f; payloadScore = 0; payloadsSeen = 0; Similarity similarity1 = getSimilarity(); while (more && doc == spans.doc()) { int matchLength = spans.end() - spans.start(); freq += similarity1.sloppyFreq(matchLength); processPayload(similarity1); more = spans.next();//this moves positions to the next match in this document } return more || (freq != 0); } protected void processPayload(Similarity similarity) throws IOException { if (positions.isPayloadAvailable()) { payload = positions.getPayload(payload, 0); payloadScore += AllBoostUtils.readFloat(payload); payloadsSeen++; } else { //zero out the payload? } } public float score() throws IOException { return super.score() * (payloadsSeen > 0 ? (payloadScore / payloadsSeen) : 1); } public Explanation explain(final int doc) throws IOException { Explanation result = new Explanation(); Explanation nonPayloadExpl = super.explain(doc); result.addDetail(nonPayloadExpl); //QUESTION: Is there a wau to avoid this skipTo call? We need to know whether to load the payload or not Explanation payloadBoost = new Explanation(); result.addDetail(payloadBoost); /* if (skipTo(doc) == true) { processPayload(); } */ float avgPayloadScore = (payloadsSeen > 0 ? (payloadScore / payloadsSeen) : 1); payloadBoost.setValue(avgPayloadScore); //GSI: I suppose we could toString the payload, but I don't think that would be a good idea payloadBoost.setDescription("scorePayload(...)"); result.setValue(nonPayloadExpl.getValue() * avgPayloadScore); result.setDescription("btq, product of:"); return result; } } } public boolean equals(Object o) { if (!(o instanceof AllBoostingTermQuery)) return false; AllBoostingTermQuery other = (AllBoostingTermQuery) o; return (this.getBoost() == other.getBoost()) && this.term.equals(other.term); } }