mirror of https://github.com/apache/lucene.git
LUCENE-6845: Merge SpanScorer into Spans
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1709964 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
55261556c7
commit
5969426d82
|
@ -271,6 +271,8 @@ Other
|
||||||
|
|
||||||
* LUCENE-6467: Simplify Query.equals. (Paul Elschot via Adrien Grand)
|
* LUCENE-6467: Simplify Query.equals. (Paul Elschot via Adrien Grand)
|
||||||
|
|
||||||
|
* LUCENE-6845: SpanScorer is now merged into Spans (Alan Woodward, David Smiley)
|
||||||
|
|
||||||
Build
|
Build
|
||||||
|
|
||||||
* LUCENE-6732: Improve checker for invalid source patterns to also
|
* LUCENE-6732: Improve checker for invalid source patterns to also
|
||||||
|
|
|
@ -19,8 +19,6 @@ package org.apache.lucene.search;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.lucene.search.spans.Spans;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This abstract class defines methods to iterate over a set of non-decreasing
|
* This abstract class defines methods to iterate over a set of non-decreasing
|
||||||
* doc ids. Note that this class assumes it iterates on doc Ids, and therefore
|
* doc ids. Note that this class assumes it iterates on doc Ids, and therefore
|
||||||
|
|
|
@ -20,11 +20,8 @@ package org.apache.lucene.search;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.apache.lucene.search.spans.Spans;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returned by {@link Scorer#asTwoPhaseIterator()}
|
* Returned by {@link Scorer#asTwoPhaseIterator()}
|
||||||
* and {@link Spans#asTwoPhaseIterator()}
|
|
||||||
* to expose an approximation of a {@link DocIdSetIterator}.
|
* to expose an approximation of a {@link DocIdSetIterator}.
|
||||||
* When the {@link #approximation()}'s
|
* When the {@link #approximation()}'s
|
||||||
* {@link DocIdSetIterator#nextDoc()} or {@link DocIdSetIterator#advance(int)}
|
* {@link DocIdSetIterator#nextDoc()} or {@link DocIdSetIterator#advance(int)}
|
||||||
|
@ -100,8 +97,6 @@ public abstract class TwoPhaseIterator {
|
||||||
public static TwoPhaseIterator asTwoPhaseIterator(DocIdSetIterator iter) {
|
public static TwoPhaseIterator asTwoPhaseIterator(DocIdSetIterator iter) {
|
||||||
return (iter instanceof Scorer)
|
return (iter instanceof Scorer)
|
||||||
? ((Scorer) iter).asTwoPhaseIterator()
|
? ((Scorer) iter).asTwoPhaseIterator()
|
||||||
: (iter instanceof Spans)
|
|
||||||
? ((Spans) iter).asTwoPhaseIterator()
|
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.util.List;
|
||||||
import org.apache.lucene.search.DocIdSetIterator;
|
import org.apache.lucene.search.DocIdSetIterator;
|
||||||
import org.apache.lucene.search.ConjunctionDISI;
|
import org.apache.lucene.search.ConjunctionDISI;
|
||||||
import org.apache.lucene.search.TwoPhaseIterator;
|
import org.apache.lucene.search.TwoPhaseIterator;
|
||||||
|
import org.apache.lucene.search.similarities.Similarity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common super class for multiple sub spans required in a document.
|
* Common super class for multiple sub spans required in a document.
|
||||||
|
@ -33,7 +34,8 @@ abstract class ConjunctionSpans extends Spans {
|
||||||
boolean atFirstInCurrentDoc; // a first start position is available in current doc for nextStartPosition
|
boolean atFirstInCurrentDoc; // a first start position is available in current doc for nextStartPosition
|
||||||
boolean oneExhaustedInCurrentDoc; // one subspans exhausted in current doc
|
boolean oneExhaustedInCurrentDoc; // one subspans exhausted in current doc
|
||||||
|
|
||||||
ConjunctionSpans(List<Spans> subSpans) {
|
ConjunctionSpans(List<Spans> subSpans, SpanWeight weight, Similarity.SimScorer docScorer) {
|
||||||
|
super(weight, docScorer);
|
||||||
if (subSpans.size() < 2) {
|
if (subSpans.size() < 2) {
|
||||||
throw new IllegalArgumentException("Less than 2 subSpans.size():" + subSpans.size());
|
throw new IllegalArgumentException("Less than 2 subSpans.size():" + subSpans.size());
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,13 +21,15 @@ import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.apache.lucene.search.similarities.Similarity;
|
||||||
|
|
||||||
abstract class ContainSpans extends ConjunctionSpans {
|
abstract class ContainSpans extends ConjunctionSpans {
|
||||||
Spans sourceSpans;
|
Spans sourceSpans;
|
||||||
Spans bigSpans;
|
Spans bigSpans;
|
||||||
Spans littleSpans;
|
Spans littleSpans;
|
||||||
|
|
||||||
ContainSpans(Spans bigSpans, Spans littleSpans, Spans sourceSpans) {
|
ContainSpans(SpanWeight weight, Similarity.SimScorer simScorer, Spans bigSpans, Spans littleSpans, Spans sourceSpans) {
|
||||||
super(Arrays.asList(bigSpans, littleSpans));
|
super(Arrays.asList(bigSpans, littleSpans), weight, simScorer);
|
||||||
this.bigSpans = Objects.requireNonNull(bigSpans);
|
this.bigSpans = Objects.requireNonNull(bigSpans);
|
||||||
this.littleSpans = Objects.requireNonNull(littleSpans);
|
this.littleSpans = Objects.requireNonNull(littleSpans);
|
||||||
this.sourceSpans = Objects.requireNonNull(sourceSpans);
|
this.sourceSpans = Objects.requireNonNull(sourceSpans);
|
||||||
|
|
|
@ -21,6 +21,7 @@ import java.io.IOException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.apache.lucene.search.TwoPhaseIterator;
|
import org.apache.lucene.search.TwoPhaseIterator;
|
||||||
|
import org.apache.lucene.search.similarities.Similarity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link Spans} implementation wrapping another spans instance,
|
* A {@link Spans} implementation wrapping another spans instance,
|
||||||
|
@ -35,7 +36,8 @@ public abstract class FilterSpans extends Spans {
|
||||||
private int startPos = -1;
|
private int startPos = -1;
|
||||||
|
|
||||||
/** Wrap the given {@link Spans}. */
|
/** Wrap the given {@link Spans}. */
|
||||||
protected FilterSpans(Spans in) {
|
protected FilterSpans(Spans in, Similarity.SimScorer docScorer) {
|
||||||
|
super((SpanWeight)in.getWeight(), docScorer);
|
||||||
this.in = Objects.requireNonNull(in);
|
this.in = Objects.requireNonNull(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +183,7 @@ public abstract class FilterSpans extends Spans {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status returned from {@link FilterSpans#accept(Spans)} that indicates
|
* Status returned from {@link FilterSpans#accept(Spans)} that indicates
|
||||||
* whether a candidate match should be accepted, rejected, or rejected
|
* whether a candidate match should be accepted, rejected, or rejected
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
package org.apache.lucene.search.spans;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Common super class for un/ordered Spans with a maximum slop between them.
|
|
||||||
*/
|
|
||||||
abstract class NearSpans extends ConjunctionSpans {
|
|
||||||
final SpanNearQuery query;
|
|
||||||
final int allowedSlop;
|
|
||||||
|
|
||||||
NearSpans(SpanNearQuery query, List<Spans> subSpans) {
|
|
||||||
super(subSpans);
|
|
||||||
this.query = query;
|
|
||||||
this.allowedSlop = query.getSlop();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -20,6 +20,8 @@ package org.apache.lucene.search.spans;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.lucene.search.similarities.Similarity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Spans that is formed from the ordered subspans of a SpanNearQuery
|
* A Spans that is formed from the ordered subspans of a SpanNearQuery
|
||||||
* where the subspans do not overlap and have a maximum slop between them.
|
* where the subspans do not overlap and have a maximum slop between them.
|
||||||
|
@ -42,15 +44,18 @@ import java.util.List;
|
||||||
* Expert:
|
* Expert:
|
||||||
* Only public for subclassing. Most implementations should not need this class
|
* Only public for subclassing. Most implementations should not need this class
|
||||||
*/
|
*/
|
||||||
public class NearSpansOrdered extends NearSpans {
|
public class NearSpansOrdered extends ConjunctionSpans {
|
||||||
|
|
||||||
protected int matchStart = -1;
|
protected int matchStart = -1;
|
||||||
protected int matchEnd = -1;
|
protected int matchEnd = -1;
|
||||||
protected int matchWidth = -1;
|
protected int matchWidth = -1;
|
||||||
|
|
||||||
public NearSpansOrdered(SpanNearQuery query, List<Spans> subSpans) throws IOException {
|
private final int allowedSlop;
|
||||||
super(query, subSpans);
|
|
||||||
|
public NearSpansOrdered(SpanWeight weight, int allowedSlop, List<Spans> subSpans, Similarity.SimScorer simScorer) throws IOException {
|
||||||
|
super(subSpans, weight, simScorer);
|
||||||
this.atFirstInCurrentDoc = true; // -1 startPosition/endPosition also at doc -1
|
this.atFirstInCurrentDoc = true; // -1 startPosition/endPosition also at doc -1
|
||||||
|
this.allowedSlop = allowedSlop;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -149,7 +154,7 @@ public class NearSpansOrdered extends NearSpans {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "NearSpansOrdered("+query.toString()+")@"+docID()+": "+startPosition()+" - "+endPosition();
|
return "NearSpansOrdered("+weight.getQuery().toString()+")@"+docID()+": "+startPosition()+" - "+endPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,28 +17,30 @@ package org.apache.lucene.search.spans;
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.apache.lucene.search.TwoPhaseIterator;
|
|
||||||
import org.apache.lucene.util.PriorityQueue;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.lucene.search.TwoPhaseIterator;
|
||||||
|
import org.apache.lucene.search.similarities.Similarity;
|
||||||
|
import org.apache.lucene.util.PriorityQueue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Similar to {@link NearSpansOrdered}, but for the unordered case.
|
* Similar to {@link NearSpansOrdered}, but for the unordered case.
|
||||||
*
|
*
|
||||||
* Expert:
|
* Expert:
|
||||||
* Only public for subclassing. Most implementations should not need this class
|
* Only public for subclassing. Most implementations should not need this class
|
||||||
*/
|
*/
|
||||||
public class NearSpansUnordered extends NearSpans {
|
public class NearSpansUnordered extends ConjunctionSpans {
|
||||||
|
|
||||||
private List<SpansCell> subSpanCells; // in query order
|
private List<SpansCell> subSpanCells; // in query order
|
||||||
|
private final int allowedSlop;
|
||||||
|
|
||||||
private SpanPositionQueue spanPositionQueue;
|
private SpanPositionQueue spanPositionQueue;
|
||||||
|
|
||||||
public NearSpansUnordered(SpanNearQuery query, List<Spans> subSpans)
|
public NearSpansUnordered(SpanWeight weight, int allowedSlop, List<Spans> subSpans, Similarity.SimScorer simScorer)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
super(query, subSpans);
|
super(subSpans, weight, simScorer);
|
||||||
|
|
||||||
this.subSpanCells = new ArrayList<>(subSpans.size());
|
this.subSpanCells = new ArrayList<>(subSpans.size());
|
||||||
for (Spans subSpan : subSpans) { // sub spans in query order
|
for (Spans subSpan : subSpans) { // sub spans in query order
|
||||||
|
@ -46,6 +48,7 @@ public class NearSpansUnordered extends NearSpans {
|
||||||
}
|
}
|
||||||
spanPositionQueue = new SpanPositionQueue(subSpans.size());
|
spanPositionQueue = new SpanPositionQueue(subSpans.size());
|
||||||
singleCellToPositionQueue(); // -1 startPosition/endPosition also at doc -1
|
singleCellToPositionQueue(); // -1 startPosition/endPosition also at doc -1
|
||||||
|
this.allowedSlop = allowedSlop;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void singleCellToPositionQueue() {
|
private void singleCellToPositionQueue() {
|
||||||
|
@ -74,6 +77,7 @@ public class NearSpansUnordered extends NearSpans {
|
||||||
final Spans in;
|
final Spans in;
|
||||||
|
|
||||||
public SpansCell(Spans spans) {
|
public SpansCell(Spans spans) {
|
||||||
|
super((SpanWeight) NearSpansUnordered.this.weight, NearSpansUnordered.this.docScorer);
|
||||||
this.in = spans;
|
this.in = spans;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +176,7 @@ public class NearSpansUnordered extends NearSpans {
|
||||||
* or the spans start at the same position,
|
* or the spans start at the same position,
|
||||||
* and spans1 ends before spans2.
|
* and spans1 ends before spans2.
|
||||||
*/
|
*/
|
||||||
static final boolean positionsOrdered(Spans spans1, Spans spans2) {
|
static boolean positionsOrdered(Spans spans1, Spans spans2) {
|
||||||
assert spans1.docID() == spans2.docID() : "doc1 " + spans1.docID() + " != doc2 " + spans2.docID();
|
assert spans1.docID() == spans2.docID() : "doc1 " + spans1.docID() + " != doc2 " + spans2.docID();
|
||||||
int start1 = spans1.startPosition();
|
int start1 = spans1.startPosition();
|
||||||
int start2 = spans2.startPosition();
|
int start2 = spans2.startPosition();
|
||||||
|
@ -261,10 +265,10 @@ public class NearSpansUnordered extends NearSpans {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if (minPositionCell() != null) {
|
if (minPositionCell() != null) {
|
||||||
return getClass().getName() + "("+query.toString()+")@"+
|
return getClass().getName() + "("+weight.getQuery().toString()+")@"+
|
||||||
(docID()+":"+startPosition()+"-"+endPosition());
|
(docID()+":"+startPosition()+"-"+endPosition());
|
||||||
} else {
|
} else {
|
||||||
return getClass().getName() + "("+query.toString()+")@ ?START?";
|
return getClass().getName() + "("+weight.getQuery().toString()+")@ ?START?";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
package org.apache.lucene.search.spans;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.search.similarities.Similarity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Spans that wraps another Spans with a different SimScorer
|
||||||
|
*/
|
||||||
|
public class ScoringWrapperSpans extends Spans {
|
||||||
|
|
||||||
|
private final Spans in;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new ScoringWrapperSpans
|
||||||
|
* @param spans the scorer to wrap
|
||||||
|
* @param simScorer the SimScorer to use for scoring
|
||||||
|
*/
|
||||||
|
public ScoringWrapperSpans(Spans spans, Similarity.SimScorer simScorer) {
|
||||||
|
super((SpanWeight) spans.getWeight(), simScorer);
|
||||||
|
this.in = spans;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nextStartPosition() throws IOException {
|
||||||
|
return in.nextStartPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int startPosition() {
|
||||||
|
return in.startPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int endPosition() {
|
||||||
|
return in.endPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int width() {
|
||||||
|
return in.width();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void collect(SpanCollector collector) throws IOException {
|
||||||
|
in.collect(collector);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int docID() {
|
||||||
|
return in.docID();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nextDoc() throws IOException {
|
||||||
|
return in.nextDoc();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int advance(int target) throws IOException {
|
||||||
|
return in.advance(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long cost() {
|
||||||
|
return in.cost();
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,16 +17,16 @@ package org.apache.lucene.search.spans;
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.lucene.index.LeafReaderContext;
|
import org.apache.lucene.index.LeafReaderContext;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
import org.apache.lucene.index.TermContext;
|
import org.apache.lucene.index.TermContext;
|
||||||
import org.apache.lucene.search.IndexSearcher;
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
|
|
||||||
import java.io.IOException;
|
/** Keep matches that contain another SpanScorer. */
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/** Keep matches that contain another Spans. */
|
|
||||||
public final class SpanContainingQuery extends SpanContainQuery {
|
public final class SpanContainingQuery extends SpanContainQuery {
|
||||||
/** Construct a SpanContainingQuery matching spans from <code>big</code>
|
/** Construct a SpanContainingQuery matching spans from <code>big</code>
|
||||||
* that contain at least one spans from <code>little</code>.
|
* that contain at least one spans from <code>little</code>.
|
||||||
|
@ -71,7 +71,7 @@ public final class SpanContainingQuery extends SpanContainQuery {
|
||||||
Spans big = containerContained.get(0);
|
Spans big = containerContained.get(0);
|
||||||
Spans little = containerContained.get(1);
|
Spans little = containerContained.get(1);
|
||||||
|
|
||||||
return new ContainSpans(big, little, big) {
|
return new ContainSpans(this, getSimScorer(context), big, little, big) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean twoPhaseCurrentDocMatches() throws IOException {
|
boolean twoPhaseCurrentDocMatches() throws IOException {
|
||||||
|
|
|
@ -33,7 +33,6 @@ import org.apache.lucene.index.TermContext;
|
||||||
import org.apache.lucene.index.Terms;
|
import org.apache.lucene.index.Terms;
|
||||||
import org.apache.lucene.search.IndexSearcher;
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.apache.lucene.util.ToStringUtils;
|
|
||||||
|
|
||||||
/** Matches spans which are near one another. One can specify <i>slop</i>, the
|
/** Matches spans which are near one another. One can specify <i>slop</i>, the
|
||||||
* maximum number of intervening unmatched positions, as well as whether
|
* maximum number of intervening unmatched positions, as well as whether
|
||||||
|
@ -220,8 +219,8 @@ public class SpanNearQuery extends SpanQuery implements Cloneable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// all NearSpans require at least two subSpans
|
// all NearSpans require at least two subSpans
|
||||||
return (!inOrder) ? new NearSpansUnordered(SpanNearQuery.this, subSpans)
|
return (!inOrder) ? new NearSpansUnordered(this, slop, subSpans, getSimScorer(context))
|
||||||
: new NearSpansOrdered(SpanNearQuery.this, subSpans);
|
: new NearSpansOrdered(this, slop, subSpans, getSimScorer(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -331,6 +330,7 @@ public class SpanNearQuery extends SpanQuery implements Cloneable {
|
||||||
final int width;
|
final int width;
|
||||||
|
|
||||||
GapSpans(int width) {
|
GapSpans(int width) {
|
||||||
|
super(null, null);
|
||||||
this.width = width;
|
this.width = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,11 @@ package org.apache.lucene.search.spans;
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.lucene.index.IndexReader;
|
import org.apache.lucene.index.IndexReader;
|
||||||
import org.apache.lucene.index.LeafReaderContext;
|
import org.apache.lucene.index.LeafReaderContext;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
|
@ -25,12 +30,6 @@ import org.apache.lucene.search.DocIdSetIterator;
|
||||||
import org.apache.lucene.search.IndexSearcher;
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.apache.lucene.search.TwoPhaseIterator;
|
import org.apache.lucene.search.TwoPhaseIterator;
|
||||||
import org.apache.lucene.util.ToStringUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/** Removes matches which overlap with another SpanQuery or which are
|
/** Removes matches which overlap with another SpanQuery or which are
|
||||||
* within x tokens before or y tokens after another SpanQuery.
|
* within x tokens before or y tokens after another SpanQuery.
|
||||||
|
@ -127,13 +126,13 @@ public final class SpanNotQuery extends SpanQuery {
|
||||||
|
|
||||||
Spans excludeSpans = excludeWeight.getSpans(context, requiredPostings);
|
Spans excludeSpans = excludeWeight.getSpans(context, requiredPostings);
|
||||||
if (excludeSpans == null) {
|
if (excludeSpans == null) {
|
||||||
return includeSpans;
|
return new ScoringWrapperSpans(includeSpans, getSimScorer(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
TwoPhaseIterator excludeTwoPhase = excludeSpans.asTwoPhaseIterator();
|
TwoPhaseIterator excludeTwoPhase = excludeSpans.asTwoPhaseIterator();
|
||||||
DocIdSetIterator excludeApproximation = excludeTwoPhase == null ? null : excludeTwoPhase.approximation();
|
DocIdSetIterator excludeApproximation = excludeTwoPhase == null ? null : excludeTwoPhase.approximation();
|
||||||
|
|
||||||
return new FilterSpans(includeSpans) {
|
return new FilterSpans(includeSpans, getSimScorer(context)) {
|
||||||
// last document we have checked matches() against for the exclusion, and failed
|
// last document we have checked matches() against for the exclusion, and failed
|
||||||
// when using approximations, so we don't call it again, and pass thru all inclusions.
|
// when using approximations, so we don't call it again, and pass thru all inclusions.
|
||||||
int lastApproxDoc = -1;
|
int lastApproxDoc = -1;
|
||||||
|
|
|
@ -17,6 +17,13 @@ package org.apache.lucene.search.spans;
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.lucene.index.IndexReader;
|
import org.apache.lucene.index.IndexReader;
|
||||||
import org.apache.lucene.index.LeafReaderContext;
|
import org.apache.lucene.index.LeafReaderContext;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
|
@ -28,13 +35,6 @@ import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.apache.lucene.search.TwoPhaseIterator;
|
import org.apache.lucene.search.TwoPhaseIterator;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
|
|
||||||
/** Matches the union of its clauses.
|
/** Matches the union of its clauses.
|
||||||
*/
|
*/
|
||||||
|
@ -166,7 +166,7 @@ public final class SpanOrQuery extends SpanQuery {
|
||||||
if (subSpans.size() == 0) {
|
if (subSpans.size() == 0) {
|
||||||
return null;
|
return null;
|
||||||
} else if (subSpans.size() == 1) {
|
} else if (subSpans.size() == 1) {
|
||||||
return subSpans.get(0);
|
return new ScoringWrapperSpans(subSpans.get(0), getSimScorer(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
DisiPriorityQueue<Spans> byDocQueue = new DisiPriorityQueue<>(subSpans.size());
|
DisiPriorityQueue<Spans> byDocQueue = new DisiPriorityQueue<>(subSpans.size());
|
||||||
|
@ -176,7 +176,7 @@ public final class SpanOrQuery extends SpanQuery {
|
||||||
|
|
||||||
SpanPositionQueue byPositionQueue = new SpanPositionQueue(subSpans.size()); // when empty use -1
|
SpanPositionQueue byPositionQueue = new SpanPositionQueue(subSpans.size()); // when empty use -1
|
||||||
|
|
||||||
return new Spans() {
|
return new Spans(this, getSimScorer(context)) {
|
||||||
Spans topPositionSpans = null;
|
Spans topPositionSpans = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -17,6 +17,11 @@ package org.apache.lucene.search.spans;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.lucene.index.IndexReader;
|
import org.apache.lucene.index.IndexReader;
|
||||||
import org.apache.lucene.index.LeafReaderContext;
|
import org.apache.lucene.index.LeafReaderContext;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
|
@ -25,11 +30,6 @@ import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.apache.lucene.search.spans.FilterSpans.AcceptStatus;
|
import org.apache.lucene.search.spans.FilterSpans.AcceptStatus;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for filtering a SpanQuery based on the position of a match.
|
* Base class for filtering a SpanQuery based on the position of a match.
|
||||||
|
@ -94,7 +94,7 @@ public abstract class SpanPositionCheckQuery extends SpanQuery implements Clonea
|
||||||
@Override
|
@Override
|
||||||
public Spans getSpans(final LeafReaderContext context, Postings requiredPostings) throws IOException {
|
public Spans getSpans(final LeafReaderContext context, Postings requiredPostings) throws IOException {
|
||||||
Spans matchSpans = matchWeight.getSpans(context, requiredPostings);
|
Spans matchSpans = matchWeight.getSpans(context, requiredPostings);
|
||||||
return (matchSpans == null) ? null : new FilterSpans(matchSpans) {
|
return (matchSpans == null) ? null : new FilterSpans(matchSpans, getSimScorer(context)) {
|
||||||
@Override
|
@Override
|
||||||
protected AcceptStatus accept(Spans candidate) throws IOException {
|
protected AcceptStatus accept(Spans candidate) throws IOException {
|
||||||
return acceptPosition(candidate);
|
return acceptPosition(candidate);
|
||||||
|
|
|
@ -1,165 +0,0 @@
|
||||||
package org.apache.lucene.search.spans;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.Objects;
|
|
||||||
|
|
||||||
import org.apache.lucene.search.Scorer;
|
|
||||||
import org.apache.lucene.search.TwoPhaseIterator;
|
|
||||||
import org.apache.lucene.search.similarities.Similarity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Public for extension only.
|
|
||||||
*/
|
|
||||||
public class SpanScorer extends Scorer {
|
|
||||||
/** underlying spans we are scoring from */
|
|
||||||
protected final Spans spans;
|
|
||||||
/** similarity used in default score impl */
|
|
||||||
protected final Similarity.SimScorer docScorer;
|
|
||||||
|
|
||||||
/** accumulated sloppy freq (computed in setFreqCurrentDoc) */
|
|
||||||
protected float freq;
|
|
||||||
/** number of matches (computed in setFreqCurrentDoc) */
|
|
||||||
protected int numMatches;
|
|
||||||
|
|
||||||
private int lastScoredDoc = -1; // last doc we called setFreqCurrentDoc() for
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new SpanScorer
|
|
||||||
* @lucene.internal
|
|
||||||
*/
|
|
||||||
public SpanScorer(Spans spans, SpanWeight weight, Similarity.SimScorer docScorer) throws IOException {
|
|
||||||
super(weight);
|
|
||||||
this.docScorer = docScorer;
|
|
||||||
this.spans = Objects.requireNonNull(spans);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final int nextDoc() throws IOException {
|
|
||||||
return spans.nextDoc();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final int advance(int target) throws IOException {
|
|
||||||
return spans.advance(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensure setFreqCurrentDoc is called, if not already called for the current doc.
|
|
||||||
*/
|
|
||||||
private final void ensureFreq() throws IOException {
|
|
||||||
int currentDoc = spans.docID();
|
|
||||||
if (lastScoredDoc != currentDoc) {
|
|
||||||
setFreqCurrentDoc();
|
|
||||||
lastScoredDoc = currentDoc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets {@link #freq} and {@link #numMatches} for the current document.
|
|
||||||
* <p>
|
|
||||||
* This will be called at most once per document.
|
|
||||||
*/
|
|
||||||
protected final void setFreqCurrentDoc() throws IOException {
|
|
||||||
freq = 0.0f;
|
|
||||||
numMatches = 0;
|
|
||||||
|
|
||||||
doStartCurrentDoc();
|
|
||||||
|
|
||||||
assert spans.startPosition() == -1 : "incorrect initial start position, spans="+spans;
|
|
||||||
assert spans.endPosition() == -1 : "incorrect initial end position, spans="+spans;
|
|
||||||
int prevStartPos = -1;
|
|
||||||
int prevEndPos = -1;
|
|
||||||
|
|
||||||
int startPos = spans.nextStartPosition();
|
|
||||||
assert startPos != Spans.NO_MORE_POSITIONS : "initial startPos NO_MORE_POSITIONS, spans="+spans;
|
|
||||||
do {
|
|
||||||
assert startPos >= prevStartPos;
|
|
||||||
int endPos = spans.endPosition();
|
|
||||||
assert endPos != Spans.NO_MORE_POSITIONS;
|
|
||||||
// This assertion can fail for Or spans on the same term:
|
|
||||||
// assert (startPos != prevStartPos) || (endPos > prevEndPos) : "non increased endPos="+endPos;
|
|
||||||
assert (startPos != prevStartPos) || (endPos >= prevEndPos) : "decreased endPos="+endPos;
|
|
||||||
numMatches++;
|
|
||||||
if (docScorer == null) { // scores not required, break out here
|
|
||||||
freq = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
freq += docScorer.computeSlopFactor(spans.width());
|
|
||||||
doCurrentSpans();
|
|
||||||
prevStartPos = startPos;
|
|
||||||
prevEndPos = endPos;
|
|
||||||
startPos = spans.nextStartPosition();
|
|
||||||
} while (startPos != Spans.NO_MORE_POSITIONS);
|
|
||||||
|
|
||||||
assert spans.startPosition() == Spans.NO_MORE_POSITIONS : "incorrect final start position, spans="+spans;
|
|
||||||
assert spans.endPosition() == Spans.NO_MORE_POSITIONS : "incorrect final end position, spans="+spans;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called before the current doc's frequency is calculated
|
|
||||||
*/
|
|
||||||
protected void doStartCurrentDoc() throws IOException {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called each time the scorer's Spans is advanced during frequency calculation
|
|
||||||
*/
|
|
||||||
protected void doCurrentSpans() throws IOException {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Score the current doc. The default implementation scores the doc
|
|
||||||
* with the similarity using the slop-adjusted {@link #freq}.
|
|
||||||
*/
|
|
||||||
protected float scoreCurrentDoc() throws IOException {
|
|
||||||
return docScorer.score(spans.docID(), freq);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final int docID() { return spans.docID(); }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final float score() throws IOException {
|
|
||||||
ensureFreq();
|
|
||||||
return scoreCurrentDoc();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final int freq() throws IOException {
|
|
||||||
ensureFreq();
|
|
||||||
return numMatches;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the intermediate "sloppy freq" adjusted for edit distance
|
|
||||||
* @lucene.internal */
|
|
||||||
// only public so .payloads can see it.
|
|
||||||
public final float sloppyFreq() throws IOException {
|
|
||||||
ensureFreq();
|
|
||||||
return freq;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final long cost() {
|
|
||||||
return spans.cost();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final TwoPhaseIterator asTwoPhaseIterator() {
|
|
||||||
return spans.asTwoPhaseIterator();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,6 +17,12 @@ package org.apache.lucene.search.spans;
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.lucene.index.IndexReaderContext;
|
import org.apache.lucene.index.IndexReaderContext;
|
||||||
import org.apache.lucene.index.LeafReaderContext;
|
import org.apache.lucene.index.LeafReaderContext;
|
||||||
import org.apache.lucene.index.PostingsEnum;
|
import org.apache.lucene.index.PostingsEnum;
|
||||||
|
@ -27,13 +33,6 @@ import org.apache.lucene.index.TermState;
|
||||||
import org.apache.lucene.index.Terms;
|
import org.apache.lucene.index.Terms;
|
||||||
import org.apache.lucene.index.TermsEnum;
|
import org.apache.lucene.index.TermsEnum;
|
||||||
import org.apache.lucene.search.IndexSearcher;
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.util.ToStringUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/** Matches spans containing a term.
|
/** Matches spans containing a term.
|
||||||
* This should not be used for terms that are indexed at position Integer.MAX_VALUE.
|
* This should not be used for terms that are indexed at position Integer.MAX_VALUE.
|
||||||
|
@ -118,7 +117,7 @@ public class SpanTermQuery extends SpanQuery {
|
||||||
termsEnum.seekExact(term.bytes(), state);
|
termsEnum.seekExact(term.bytes(), state);
|
||||||
|
|
||||||
final PostingsEnum postings = termsEnum.postings(null, requiredPostings.getRequiredPostings());
|
final PostingsEnum postings = termsEnum.postings(null, requiredPostings.getRequiredPostings());
|
||||||
return new TermSpans(postings, term);
|
return new TermSpans(this, getSimScorer(context), postings, term);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ import org.apache.lucene.index.LeafReaderContext;
|
||||||
import org.apache.lucene.index.PostingsEnum;
|
import org.apache.lucene.index.PostingsEnum;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
import org.apache.lucene.index.TermContext;
|
import org.apache.lucene.index.TermContext;
|
||||||
import org.apache.lucene.index.Terms;
|
|
||||||
import org.apache.lucene.search.CollectionStatistics;
|
import org.apache.lucene.search.CollectionStatistics;
|
||||||
import org.apache.lucene.search.Explanation;
|
import org.apache.lucene.search.Explanation;
|
||||||
import org.apache.lucene.search.IndexSearcher;
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
|
@ -132,25 +131,22 @@ public abstract class SpanWeight extends Weight {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Scorer scorer(LeafReaderContext context) throws IOException {
|
public Scorer scorer(LeafReaderContext context) throws IOException {
|
||||||
if (field == null) {
|
return getSpans(context, Postings.POSITIONS);
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Terms terms = context.reader().terms(field);
|
|
||||||
if (terms != null && terms.hasPositions() == false) {
|
|
||||||
throw new IllegalStateException("field \"" + field + "\" was indexed without position data; cannot run SpanQuery (query=" + parentQuery + ")");
|
|
||||||
}
|
|
||||||
Spans spans = getSpans(context, Postings.POSITIONS);
|
|
||||||
Similarity.SimScorer simScorer = getSimScorer(context);
|
|
||||||
return (spans == null) ? null : new SpanScorer(spans, this, simScorer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a SimScorer for this context
|
||||||
|
* @param context the LeafReaderContext
|
||||||
|
* @return a SimWeight
|
||||||
|
* @throws IOException on error
|
||||||
|
*/
|
||||||
public Similarity.SimScorer getSimScorer(LeafReaderContext context) throws IOException {
|
public Similarity.SimScorer getSimScorer(LeafReaderContext context) throws IOException {
|
||||||
return simWeight == null ? null : similarity.simScorer(simWeight, context);
|
return simWeight == null ? null : similarity.simScorer(simWeight, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Explanation explain(LeafReaderContext context, int doc) throws IOException {
|
public Explanation explain(LeafReaderContext context, int doc) throws IOException {
|
||||||
SpanScorer scorer = (SpanScorer) scorer(context);
|
Spans scorer = (Spans) scorer(context);
|
||||||
if (scorer != null) {
|
if (scorer != null) {
|
||||||
int newDoc = scorer.advance(doc);
|
int newDoc = scorer.advance(doc);
|
||||||
if (newDoc == doc) {
|
if (newDoc == doc) {
|
||||||
|
|
|
@ -17,15 +17,15 @@ package org.apache.lucene.search.spans;
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.lucene.index.LeafReaderContext;
|
import org.apache.lucene.index.LeafReaderContext;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
import org.apache.lucene.index.TermContext;
|
import org.apache.lucene.index.TermContext;
|
||||||
import org.apache.lucene.search.IndexSearcher;
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/** Keep matches that are contained within another Spans. */
|
/** Keep matches that are contained within another Spans. */
|
||||||
public final class SpanWithinQuery extends SpanContainQuery {
|
public final class SpanWithinQuery extends SpanContainQuery {
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ public final class SpanWithinQuery extends SpanContainQuery {
|
||||||
Spans big = containerContained.get(0);
|
Spans big = containerContained.get(0);
|
||||||
Spans little = containerContained.get(1);
|
Spans little = containerContained.get(1);
|
||||||
|
|
||||||
return new ContainSpans(big, little, little) {
|
return new ContainSpans(this, getSimScorer(context), big, little, little) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean twoPhaseCurrentDocMatches() throws IOException {
|
boolean twoPhaseCurrentDocMatches() throws IOException {
|
||||||
|
|
|
@ -19,8 +19,8 @@ package org.apache.lucene.search.spans;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.lucene.search.DocIdSetIterator;
|
import org.apache.lucene.search.Scorer;
|
||||||
import org.apache.lucene.search.TwoPhaseIterator;
|
import org.apache.lucene.search.similarities.Similarity;
|
||||||
import org.apache.lucene.search.similarities.Similarity.SimScorer;
|
import org.apache.lucene.search.similarities.Similarity.SimScorer;
|
||||||
|
|
||||||
/** Iterates through combinations of start/end positions per-doc.
|
/** Iterates through combinations of start/end positions per-doc.
|
||||||
|
@ -28,9 +28,24 @@ import org.apache.lucene.search.similarities.Similarity.SimScorer;
|
||||||
* These are enumerated in order, by increasing document number, within that by
|
* These are enumerated in order, by increasing document number, within that by
|
||||||
* increasing start position and finally by increasing end position.
|
* increasing start position and finally by increasing end position.
|
||||||
*/
|
*/
|
||||||
public abstract class Spans extends DocIdSetIterator {
|
public abstract class Spans extends Scorer {
|
||||||
|
|
||||||
public static final int NO_MORE_POSITIONS = Integer.MAX_VALUE;
|
public static final int NO_MORE_POSITIONS = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
protected final Similarity.SimScorer docScorer;
|
||||||
|
|
||||||
|
protected Spans(SpanWeight weight, SimScorer docScorer) {
|
||||||
|
super(weight);
|
||||||
|
this.docScorer = docScorer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** accumulated sloppy freq (computed in setFreqCurrentDoc) */
|
||||||
|
protected float freq;
|
||||||
|
/** number of matches (computed in setFreqCurrentDoc) */
|
||||||
|
protected int numMatches;
|
||||||
|
|
||||||
|
private int lastScoredDoc = -1; // last doc we called setFreqCurrentDoc() for
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the next start position for the current doc.
|
* Returns the next start position for the current doc.
|
||||||
* There is always at least one start/end position per doc.
|
* There is always at least one start/end position per doc.
|
||||||
|
@ -71,26 +86,6 @@ public abstract class Spans extends DocIdSetIterator {
|
||||||
*/
|
*/
|
||||||
public abstract void collect(SpanCollector collector) throws IOException;
|
public abstract void collect(SpanCollector collector) throws IOException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Optional method: Return a {@link TwoPhaseIterator} view of this
|
|
||||||
* {@link Spans}. A return value of {@code null} indicates that
|
|
||||||
* two-phase iteration is not supported.
|
|
||||||
*
|
|
||||||
* Note that the returned {@link TwoPhaseIterator}'s
|
|
||||||
* {@link TwoPhaseIterator#approximation() approximation} must
|
|
||||||
* advance documents synchronously with this iterator:
|
|
||||||
* advancing the approximation must
|
|
||||||
* advance this iterator and vice-versa.
|
|
||||||
*
|
|
||||||
* Implementing this method is typically useful on a {@link Spans}
|
|
||||||
* that has a high per-document overhead for confirming matches.
|
|
||||||
*
|
|
||||||
* The default implementation returns {@code null}.
|
|
||||||
*/
|
|
||||||
public TwoPhaseIterator asTwoPhaseIterator() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
@ -103,4 +98,94 @@ public abstract class Spans extends DocIdSetIterator {
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure setFreqCurrentDoc is called, if not already called for the current doc.
|
||||||
|
*/
|
||||||
|
private void ensureFreq() throws IOException {
|
||||||
|
int currentDoc = docID();
|
||||||
|
if (lastScoredDoc != currentDoc) {
|
||||||
|
setFreqCurrentDoc();
|
||||||
|
lastScoredDoc = currentDoc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets {@link #freq} and {@link #numMatches} for the current document.
|
||||||
|
* <p>
|
||||||
|
* This will be called at most once per document.
|
||||||
|
*/
|
||||||
|
protected final void setFreqCurrentDoc() throws IOException {
|
||||||
|
freq = 0.0f;
|
||||||
|
numMatches = 0;
|
||||||
|
|
||||||
|
doStartCurrentDoc();
|
||||||
|
|
||||||
|
assert startPosition() == -1 : "incorrect initial start position, " + this.toString();
|
||||||
|
assert endPosition() == -1 : "incorrect initial end position, " + this.toString();
|
||||||
|
int prevStartPos = -1;
|
||||||
|
int prevEndPos = -1;
|
||||||
|
|
||||||
|
int startPos = nextStartPosition();
|
||||||
|
assert startPos != Spans.NO_MORE_POSITIONS : "initial startPos NO_MORE_POSITIONS, " + this.toString();
|
||||||
|
do {
|
||||||
|
assert startPos >= prevStartPos;
|
||||||
|
int endPos = endPosition();
|
||||||
|
assert endPos != Spans.NO_MORE_POSITIONS;
|
||||||
|
// This assertion can fail for Or spans on the same term:
|
||||||
|
// assert (startPos != prevStartPos) || (endPos > prevEndPos) : "non increased endPos="+endPos;
|
||||||
|
assert (startPos != prevStartPos) || (endPos >= prevEndPos) : "decreased endPos="+endPos;
|
||||||
|
numMatches++;
|
||||||
|
if (docScorer == null) { // scores not required, break out here
|
||||||
|
freq = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
freq += docScorer.computeSlopFactor(width());
|
||||||
|
doCurrentSpans();
|
||||||
|
prevStartPos = startPos;
|
||||||
|
prevEndPos = endPos;
|
||||||
|
startPos = nextStartPosition();
|
||||||
|
} while (startPos != Spans.NO_MORE_POSITIONS);
|
||||||
|
|
||||||
|
assert startPosition() == Spans.NO_MORE_POSITIONS : "incorrect final start position, " + this.toString();
|
||||||
|
assert endPosition() == Spans.NO_MORE_POSITIONS : "incorrect final end position, " + this.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called before the current doc's frequency is calculated
|
||||||
|
*/
|
||||||
|
protected void doStartCurrentDoc() throws IOException {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called each time the scorer's SpanScorer is advanced during frequency calculation
|
||||||
|
*/
|
||||||
|
protected void doCurrentSpans() throws IOException {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Score the current doc. The default implementation scores the doc
|
||||||
|
* with the similarity using the slop-adjusted {@link #freq}.
|
||||||
|
*/
|
||||||
|
protected float scoreCurrentDoc() throws IOException {
|
||||||
|
assert docScorer != null : getClass() + " has a null docScorer!";
|
||||||
|
return docScorer.score(docID(), freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final float score() throws IOException {
|
||||||
|
ensureFreq();
|
||||||
|
return scoreCurrentDoc();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final int freq() throws IOException {
|
||||||
|
ensureFreq();
|
||||||
|
return numMatches;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the intermediate "sloppy freq" adjusted for edit distance
|
||||||
|
* @lucene.internal */
|
||||||
|
final float sloppyFreq() throws IOException {
|
||||||
|
ensureFreq();
|
||||||
|
return freq;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,12 +16,13 @@ package org.apache.lucene.search.spans;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.apache.lucene.index.PostingsEnum;
|
import org.apache.lucene.index.PostingsEnum;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
import org.apache.lucene.search.DocIdSetIterator;
|
import org.apache.lucene.search.DocIdSetIterator;
|
||||||
|
import org.apache.lucene.search.similarities.Similarity;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expert:
|
* Expert:
|
||||||
|
@ -37,7 +38,8 @@ public class TermSpans extends Spans {
|
||||||
protected int position;
|
protected int position;
|
||||||
protected boolean readPayload;
|
protected boolean readPayload;
|
||||||
|
|
||||||
public TermSpans(PostingsEnum postings, Term term) {
|
public TermSpans(SpanWeight weight, Similarity.SimScorer scorer, PostingsEnum postings, Term term) {
|
||||||
|
super(weight, scorer);
|
||||||
this.postings = Objects.requireNonNull(postings);
|
this.postings = Objects.requireNonNull(postings);
|
||||||
this.term = Objects.requireNonNull(term);
|
this.term = Objects.requireNonNull(term);
|
||||||
this.doc = -1;
|
this.doc = -1;
|
||||||
|
|
|
@ -42,9 +42,9 @@ import org.apache.lucene.search.spans.MultiSpansWrapper;
|
||||||
import org.apache.lucene.search.spans.SpanCollector;
|
import org.apache.lucene.search.spans.SpanCollector;
|
||||||
import org.apache.lucene.search.spans.SpanNearQuery;
|
import org.apache.lucene.search.spans.SpanNearQuery;
|
||||||
import org.apache.lucene.search.spans.SpanQuery;
|
import org.apache.lucene.search.spans.SpanQuery;
|
||||||
|
import org.apache.lucene.search.spans.Spans;
|
||||||
import org.apache.lucene.search.spans.SpanTermQuery;
|
import org.apache.lucene.search.spans.SpanTermQuery;
|
||||||
import org.apache.lucene.search.spans.SpanWeight;
|
import org.apache.lucene.search.spans.SpanWeight;
|
||||||
import org.apache.lucene.search.spans.Spans;
|
|
||||||
import org.apache.lucene.store.Directory;
|
import org.apache.lucene.store.Directory;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.apache.lucene.util.LuceneTestCase;
|
import org.apache.lucene.util.LuceneTestCase;
|
||||||
|
|
|
@ -20,7 +20,6 @@ package org.apache.lucene.search.spans;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.lucene.search.IndexSearcher;
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.search.similarities.Similarity;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds all implementations of classes in the o.a.l.s.spans package as a
|
* Holds all implementations of classes in the o.a.l.s.spans package as a
|
||||||
|
@ -35,6 +34,10 @@ final class JustCompileSearchSpans {
|
||||||
|
|
||||||
static final class JustCompileSpans extends Spans {
|
static final class JustCompileSpans extends Spans {
|
||||||
|
|
||||||
|
JustCompileSpans() {
|
||||||
|
super(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int docID() {
|
public int docID() {
|
||||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||||
|
@ -100,65 +103,4 @@ final class JustCompileSearchSpans {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class JustCompilePayloadSpans extends Spans {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int docID() {
|
|
||||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int nextDoc() throws IOException {
|
|
||||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int advance(int target) throws IOException {
|
|
||||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int startPosition() {
|
|
||||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int endPosition() {
|
|
||||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int width() {
|
|
||||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void collect(SpanCollector collector) throws IOException {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int nextStartPosition() throws IOException {
|
|
||||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long cost() {
|
|
||||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class JustCompileSpanScorer extends SpanScorer {
|
|
||||||
|
|
||||||
protected JustCompileSpanScorer(Spans spans, SpanWeight weight,
|
|
||||||
Similarity.SimScorer docScorer) throws IOException {
|
|
||||||
super(spans, weight, docScorer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected float scoreCurrentDoc() throws IOException {
|
|
||||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,8 @@ public class TestFilterSpans extends LuceneTestCase {
|
||||||
// verify that all methods of Spans are overridden by FilterSpans,
|
// verify that all methods of Spans are overridden by FilterSpans,
|
||||||
// except those under the 'exclude' list
|
// except those under the 'exclude' list
|
||||||
Set<Method> exclude = new HashSet<>();
|
Set<Method> exclude = new HashSet<>();
|
||||||
|
exclude.add(FilterSpans.class.getMethod("freq"));
|
||||||
|
exclude.add(FilterSpans.class.getMethod("score"));
|
||||||
for (Method m : FilterSpans.class.getMethods()) {
|
for (Method m : FilterSpans.class.getMethods()) {
|
||||||
if (m.getDeclaringClass() == Spans.class) {
|
if (m.getDeclaringClass() == Spans.class) {
|
||||||
assertTrue("method " + m.getName() + " not overridden!", exclude.contains(m));
|
assertTrue("method " + m.getName() + " not overridden!", exclude.contains(m));
|
||||||
|
|
|
@ -63,9 +63,9 @@ import org.apache.lucene.search.spans.SpanNearQuery;
|
||||||
import org.apache.lucene.search.spans.SpanNotQuery;
|
import org.apache.lucene.search.spans.SpanNotQuery;
|
||||||
import org.apache.lucene.search.spans.SpanOrQuery;
|
import org.apache.lucene.search.spans.SpanOrQuery;
|
||||||
import org.apache.lucene.search.spans.SpanQuery;
|
import org.apache.lucene.search.spans.SpanQuery;
|
||||||
|
import org.apache.lucene.search.spans.Spans;
|
||||||
import org.apache.lucene.search.spans.SpanTermQuery;
|
import org.apache.lucene.search.spans.SpanTermQuery;
|
||||||
import org.apache.lucene.search.spans.SpanWeight;
|
import org.apache.lucene.search.spans.SpanWeight;
|
||||||
import org.apache.lucene.search.spans.Spans;
|
|
||||||
import org.apache.lucene.util.Bits;
|
import org.apache.lucene.util.Bits;
|
||||||
import org.apache.lucene.util.IOUtils;
|
import org.apache.lucene.util.IOUtils;
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ package org.apache.lucene.queries.payloads;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.apache.lucene.search.Explanation;
|
import org.apache.lucene.search.Explanation;
|
||||||
|
import org.apache.lucene.search.spans.Spans;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract class that defines a way for PayloadScoreQuery instances to transform
|
* An abstract class that defines a way for PayloadScoreQuery instances to transform
|
||||||
|
@ -41,7 +42,7 @@ public abstract class PayloadFunction {
|
||||||
* @param currentPayloadScore The score for the current payload
|
* @param currentPayloadScore The score for the current payload
|
||||||
* @return The new current Score
|
* @return The new current Score
|
||||||
*
|
*
|
||||||
* @see org.apache.lucene.search.spans.Spans
|
* @see Spans
|
||||||
*/
|
*/
|
||||||
public abstract float currentScore(int docId, String field, int start, int end, int numPayloadsSeen, float currentScore, float currentPayloadScore);
|
public abstract float currentScore(int docId, String field, int start, int end, int numPayloadsSeen, float currentScore, float currentPayloadScore);
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,6 @@ import org.apache.lucene.search.similarities.ClassicSimilarity;
|
||||||
import org.apache.lucene.search.similarities.Similarity;
|
import org.apache.lucene.search.similarities.Similarity;
|
||||||
import org.apache.lucene.search.spans.SpanCollector;
|
import org.apache.lucene.search.spans.SpanCollector;
|
||||||
import org.apache.lucene.search.spans.SpanQuery;
|
import org.apache.lucene.search.spans.SpanQuery;
|
||||||
import org.apache.lucene.search.spans.SpanScorer;
|
|
||||||
import org.apache.lucene.search.spans.SpanWeight;
|
import org.apache.lucene.search.spans.SpanWeight;
|
||||||
import org.apache.lucene.search.spans.Spans;
|
import org.apache.lucene.search.spans.Spans;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
|
@ -137,7 +136,7 @@ public class PayloadScoreQuery extends SpanQuery {
|
||||||
Spans spans = getSpans(context, Postings.PAYLOADS);
|
Spans spans = getSpans(context, Postings.PAYLOADS);
|
||||||
if (spans == null)
|
if (spans == null)
|
||||||
return null;
|
return null;
|
||||||
return new PayloadSpanScorer(spans, this, innerWeight.getSimScorer(context));
|
return new PayloadSpans(spans, this, innerWeight.getSimScorer(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -157,7 +156,7 @@ public class PayloadScoreQuery extends SpanQuery {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Explanation explain(LeafReaderContext context, int doc) throws IOException {
|
public Explanation explain(LeafReaderContext context, int doc) throws IOException {
|
||||||
PayloadSpanScorer scorer = (PayloadSpanScorer) scorer(context);
|
PayloadSpans scorer = (PayloadSpans) scorer(context);
|
||||||
if (scorer == null || scorer.advance(doc) != doc)
|
if (scorer == null || scorer.advance(doc) != doc)
|
||||||
return Explanation.noMatch("No match");
|
return Explanation.noMatch("No match");
|
||||||
|
|
||||||
|
@ -174,13 +173,40 @@ public class PayloadScoreQuery extends SpanQuery {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PayloadSpanScorer extends SpanScorer implements SpanCollector {
|
private class PayloadSpans extends Spans implements SpanCollector {
|
||||||
|
|
||||||
private int payloadsSeen;
|
private int payloadsSeen;
|
||||||
private float payloadScore;
|
private float payloadScore;
|
||||||
|
private final Spans in;
|
||||||
|
|
||||||
private PayloadSpanScorer(Spans spans, SpanWeight weight, Similarity.SimScorer docScorer) throws IOException {
|
private PayloadSpans(Spans spans, SpanWeight weight, Similarity.SimScorer docScorer) throws IOException {
|
||||||
super(spans, weight, docScorer);
|
super(weight, docScorer);
|
||||||
|
this.in = spans;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nextStartPosition() throws IOException {
|
||||||
|
return in.nextStartPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int startPosition() {
|
||||||
|
return in.startPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int endPosition() {
|
||||||
|
return in.endPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int width() {
|
||||||
|
return in.width();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void collect(SpanCollector collector) throws IOException {
|
||||||
|
in.collect(collector);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -191,7 +217,7 @@ public class PayloadScoreQuery extends SpanQuery {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doCurrentSpans() throws IOException {
|
protected void doCurrentSpans() throws IOException {
|
||||||
spans.collect(this);
|
in.collect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -199,8 +225,8 @@ public class PayloadScoreQuery extends SpanQuery {
|
||||||
BytesRef payload = postings.getPayload();
|
BytesRef payload = postings.getPayload();
|
||||||
if (payload == null)
|
if (payload == null)
|
||||||
return;
|
return;
|
||||||
float payloadFactor = docScorer.computePayloadFactor(docID(), spans.startPosition(), spans.endPosition(), payload);
|
float payloadFactor = docScorer.computePayloadFactor(docID(), in.startPosition(), in.endPosition(), payload);
|
||||||
payloadScore = function.currentScore(docID(), getField(), spans.startPosition(), spans.endPosition(),
|
payloadScore = function.currentScore(docID(), getField(), in.startPosition(), in.endPosition(),
|
||||||
payloadsSeen, payloadScore, payloadFactor);
|
payloadsSeen, payloadScore, payloadFactor);
|
||||||
payloadsSeen++;
|
payloadsSeen++;
|
||||||
}
|
}
|
||||||
|
@ -228,6 +254,26 @@ public class PayloadScoreQuery extends SpanQuery {
|
||||||
public void reset() {
|
public void reset() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int docID() {
|
||||||
|
return in.docID();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nextDoc() throws IOException {
|
||||||
|
return in.nextDoc();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int advance(int target) throws IOException {
|
||||||
|
return in.advance(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long cost() {
|
||||||
|
return in.cost();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,12 +28,10 @@ import org.apache.lucene.index.TermContext;
|
||||||
import org.apache.lucene.index.Terms;
|
import org.apache.lucene.index.Terms;
|
||||||
import org.apache.lucene.search.IndexSearcher;
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.search.Scorer;
|
import org.apache.lucene.search.Scorer;
|
||||||
import org.apache.lucene.search.similarities.Similarity;
|
|
||||||
import org.apache.lucene.search.spans.FilterSpans;
|
import org.apache.lucene.search.spans.FilterSpans;
|
||||||
import org.apache.lucene.search.spans.FilterSpans.AcceptStatus;
|
import org.apache.lucene.search.spans.FilterSpans.AcceptStatus;
|
||||||
import org.apache.lucene.search.spans.SpanCollector;
|
import org.apache.lucene.search.spans.SpanCollector;
|
||||||
import org.apache.lucene.search.spans.SpanQuery;
|
import org.apache.lucene.search.spans.SpanQuery;
|
||||||
import org.apache.lucene.search.spans.SpanScorer;
|
|
||||||
import org.apache.lucene.search.spans.SpanWeight;
|
import org.apache.lucene.search.spans.SpanWeight;
|
||||||
import org.apache.lucene.search.spans.Spans;
|
import org.apache.lucene.search.spans.Spans;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
|
@ -92,7 +90,7 @@ public class SpanPayloadCheckQuery extends SpanQuery {
|
||||||
public Spans getSpans(final LeafReaderContext context, Postings requiredPostings) throws IOException {
|
public Spans getSpans(final LeafReaderContext context, Postings requiredPostings) throws IOException {
|
||||||
final PayloadChecker collector = new PayloadChecker();
|
final PayloadChecker collector = new PayloadChecker();
|
||||||
Spans matchSpans = matchWeight.getSpans(context, requiredPostings.atLeast(Postings.PAYLOADS));
|
Spans matchSpans = matchWeight.getSpans(context, requiredPostings.atLeast(Postings.PAYLOADS));
|
||||||
return (matchSpans == null) ? null : new FilterSpans(matchSpans) {
|
return (matchSpans == null) ? null : new FilterSpans(matchSpans, getSimScorer(context)) {
|
||||||
@Override
|
@Override
|
||||||
protected AcceptStatus accept(Spans candidate) throws IOException {
|
protected AcceptStatus accept(Spans candidate) throws IOException {
|
||||||
collector.reset();
|
collector.reset();
|
||||||
|
@ -112,9 +110,7 @@ public class SpanPayloadCheckQuery extends SpanQuery {
|
||||||
throw new IllegalStateException("field \"" + field + "\" was indexed without position data; cannot run SpanQuery (query=" + parentQuery + ")");
|
throw new IllegalStateException("field \"" + field + "\" was indexed without position data; cannot run SpanQuery (query=" + parentQuery + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
Spans spans = getSpans(context, Postings.PAYLOADS);
|
return getSpans(context, Postings.PAYLOADS);
|
||||||
Similarity.SimScorer simScorer = simWeight == null ? null : similarity.simScorer(simWeight, context);
|
|
||||||
return (spans == null) ? null : new SpanScorer(spans, this, simScorer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,9 +48,9 @@ import org.apache.lucene.search.spans.SpanFirstQuery;
|
||||||
import org.apache.lucene.search.spans.SpanNearQuery;
|
import org.apache.lucene.search.spans.SpanNearQuery;
|
||||||
import org.apache.lucene.search.spans.SpanNotQuery;
|
import org.apache.lucene.search.spans.SpanNotQuery;
|
||||||
import org.apache.lucene.search.spans.SpanQuery;
|
import org.apache.lucene.search.spans.SpanQuery;
|
||||||
|
import org.apache.lucene.search.spans.Spans;
|
||||||
import org.apache.lucene.search.spans.SpanTermQuery;
|
import org.apache.lucene.search.spans.SpanTermQuery;
|
||||||
import org.apache.lucene.search.spans.SpanWeight;
|
import org.apache.lucene.search.spans.SpanWeight;
|
||||||
import org.apache.lucene.search.spans.Spans;
|
|
||||||
import org.apache.lucene.store.Directory;
|
import org.apache.lucene.store.Directory;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.apache.lucene.util.LuceneTestCase;
|
import org.apache.lucene.util.LuceneTestCase;
|
||||||
|
|
|
@ -41,8 +41,8 @@ import org.apache.lucene.search.similarities.ClassicSimilarity;
|
||||||
import org.apache.lucene.search.similarities.Similarity;
|
import org.apache.lucene.search.similarities.Similarity;
|
||||||
import org.apache.lucene.search.spans.MultiSpansWrapper;
|
import org.apache.lucene.search.spans.MultiSpansWrapper;
|
||||||
import org.apache.lucene.search.spans.SpanQuery;
|
import org.apache.lucene.search.spans.SpanQuery;
|
||||||
import org.apache.lucene.search.spans.SpanTermQuery;
|
|
||||||
import org.apache.lucene.search.spans.Spans;
|
import org.apache.lucene.search.spans.Spans;
|
||||||
|
import org.apache.lucene.search.spans.SpanTermQuery;
|
||||||
import org.apache.lucene.store.Directory;
|
import org.apache.lucene.store.Directory;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.apache.lucene.util.English;
|
import org.apache.lucene.util.English;
|
||||||
|
|
|
@ -38,9 +38,9 @@ import org.apache.lucene.search.TermQuery;
|
||||||
import org.apache.lucene.search.spans.SpanNearQuery;
|
import org.apache.lucene.search.spans.SpanNearQuery;
|
||||||
import org.apache.lucene.search.spans.SpanOrQuery;
|
import org.apache.lucene.search.spans.SpanOrQuery;
|
||||||
import org.apache.lucene.search.spans.SpanQuery;
|
import org.apache.lucene.search.spans.SpanQuery;
|
||||||
|
import org.apache.lucene.search.spans.Spans;
|
||||||
import org.apache.lucene.search.spans.SpanTermQuery;
|
import org.apache.lucene.search.spans.SpanTermQuery;
|
||||||
import org.apache.lucene.search.spans.SpanWeight;
|
import org.apache.lucene.search.spans.SpanWeight;
|
||||||
import org.apache.lucene.search.spans.Spans;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Experimental class to get set of payloads for most standard Lucene queries.
|
* Experimental class to get set of payloads for most standard Lucene queries.
|
||||||
|
|
|
@ -17,16 +17,17 @@ package org.apache.lucene.search.spans;
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.lucene.index.LeafReaderContext;
|
import org.apache.lucene.index.LeafReaderContext;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
import org.apache.lucene.index.TermContext;
|
import org.apache.lucene.index.TermContext;
|
||||||
import org.apache.lucene.search.Explanation;
|
import org.apache.lucene.search.Explanation;
|
||||||
import org.apache.lucene.search.IndexSearcher;
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.search.Scorer;
|
import org.apache.lucene.search.Scorer;
|
||||||
|
import org.apache.lucene.search.similarities.Similarity;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps a SpanWeight with additional asserts
|
* Wraps a SpanWeight with additional asserts
|
||||||
|
@ -55,7 +56,12 @@ public class AssertingSpanWeight extends SpanWeight {
|
||||||
Spans spans = in.getSpans(context, requiredPostings);
|
Spans spans = in.getSpans(context, requiredPostings);
|
||||||
if (spans == null)
|
if (spans == null)
|
||||||
return null;
|
return null;
|
||||||
return new AssertingSpans(spans);
|
return new AssertingSpans(spans, in.getSimScorer(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Similarity.SimScorer getSimScorer(LeafReaderContext context) throws IOException {
|
||||||
|
return in.getSimScorer(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -17,13 +17,14 @@ package org.apache.lucene.search.spans;
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.apache.lucene.search.DocIdSetIterator;
|
|
||||||
import org.apache.lucene.search.TwoPhaseIterator;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.lucene.search.DocIdSetIterator;
|
||||||
|
import org.apache.lucene.search.TwoPhaseIterator;
|
||||||
|
import org.apache.lucene.search.similarities.Similarity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps a Spans with additional asserts
|
* Wraps a Spans with additional asserts
|
||||||
*/
|
*/
|
||||||
class AssertingSpans extends Spans {
|
class AssertingSpans extends Spans {
|
||||||
final Spans in;
|
final Spans in;
|
||||||
|
@ -67,7 +68,8 @@ class AssertingSpans extends Spans {
|
||||||
|
|
||||||
State state = State.DOC_START;
|
State state = State.DOC_START;
|
||||||
|
|
||||||
AssertingSpans(Spans in) {
|
AssertingSpans(Spans in, Similarity.SimScorer docScorer) {
|
||||||
|
super((SpanWeight)in.getWeight(), docScorer);
|
||||||
this.in = in;
|
this.in = in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +189,13 @@ class AssertingSpans extends Spans {
|
||||||
public long cost() {
|
public long cost() {
|
||||||
return in.cost();
|
return in.cost();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float scoreCurrentDoc() throws IOException {
|
||||||
|
assert in.docScorer != null : in.getClass() + " has no docScorer!";
|
||||||
|
return in.scoreCurrentDoc();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TwoPhaseIterator asTwoPhaseIterator() {
|
public TwoPhaseIterator asTwoPhaseIterator() {
|
||||||
final TwoPhaseIterator iterator = in.asTwoPhaseIterator();
|
final TwoPhaseIterator iterator = in.asTwoPhaseIterator();
|
||||||
|
@ -196,7 +204,7 @@ class AssertingSpans extends Spans {
|
||||||
}
|
}
|
||||||
return new AssertingTwoPhaseView(iterator);
|
return new AssertingTwoPhaseView(iterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
class AssertingTwoPhaseView extends TwoPhaseIterator {
|
class AssertingTwoPhaseView extends TwoPhaseIterator {
|
||||||
final TwoPhaseIterator in;
|
final TwoPhaseIterator in;
|
||||||
int lastDoc = -1;
|
int lastDoc = -1;
|
||||||
|
|
Loading…
Reference in New Issue