Index: lucene/core/src/java/org/apache/lucene/search/positions/ConjunctionIntervalIterator.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/positions/ConjunctionIntervalIterator.java (revision 1400508)
+++ lucene/core/src/java/org/apache/lucene/search/positions/ConjunctionIntervalIterator.java (working copy)
@@ -16,13 +16,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import java.io.IOException;
-
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.positions.IntervalQueue.IntervalRef;
-import org.apache.lucene.util.ArrayUtil;
-import org.apache.lucene.util.RamUsageEstimator;
+import java.io.IOException;
+
/**
* ConjuctionPositionIterator based on minimal interval semantics for AND
* operator.
@@ -104,7 +102,7 @@
for (int i = 0; i < iterators.length; i++) {
int scorerAdvanced = iterators[i].scorerAdvanced(docId);
if (scorerAdvanced != docId) {
- System.out.println();
+ System.out.println(); // nocommit!
}
assert scorerAdvanced == docId;
final Interval interval = iterators[i].next();
@@ -146,91 +144,6 @@
snapshot.replay(collector);
}
}
-
- /*
- * Due to the laziness of this position iterator and the minimizing algorithm
- * we advance the underlying iterators before the consumer can call collect on
- * the top level iterator. If we need to collect positions we need to record
- * the last possible match in order to allow the consumer to get the right
- * positions for the match. This is particularly important if leaf positions
- * are required.
- */
- private static final class SnapshotPositionCollector implements
- IntervalCollector {
- private SingleSnapshot[] snapshots;
- private int index = 0;
-
- SnapshotPositionCollector(int subs) {
- snapshots = new SingleSnapshot[subs];
- }
-
- @Override
- public void collectLeafPosition(Scorer scorer, Interval interval,
- int docID) {
- collect(scorer, interval, docID, true);
-
- }
-
- private void collect(Scorer scorer, Interval interval, int docID,
- boolean isLeaf) {
- if (snapshots.length <= index) {
- grow(ArrayUtil.oversize(index + 1,
- (RamUsageEstimator.NUM_BYTES_OBJECT_REF * 2)
- + RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
- + RamUsageEstimator.NUM_BYTES_BOOLEAN
- + RamUsageEstimator.NUM_BYTES_INT));
- }
- if (snapshots[index] == null) {
- snapshots[index] = new SingleSnapshot();
- }
- snapshots[index++].set(scorer, interval, isLeaf, docID);
- }
-
- @Override
- public void collectComposite(Scorer scorer, Interval interval,
- int docID) {
- collect(scorer, interval, docID, false);
- }
-
- void replay(IntervalCollector collector) {
- for (int i = 0; i < index; i++) {
- SingleSnapshot singleSnapshot = snapshots[i];
- if (singleSnapshot.isLeaf) {
- collector.collectLeafPosition(singleSnapshot.scorer,
- singleSnapshot.interval, singleSnapshot.docID);
- } else {
- collector.collectComposite(singleSnapshot.scorer,
- singleSnapshot.interval, singleSnapshot.docID);
- }
- }
- }
-
- void reset() {
- index = 0;
- }
-
- private void grow(int size) {
- final SingleSnapshot[] newArray = new SingleSnapshot[size];
- System.arraycopy(snapshots, 0, newArray, 0, index);
- snapshots = newArray;
- }
-
- private static final class SingleSnapshot {
- Scorer scorer;
- final Interval interval = new Interval();
- boolean isLeaf;
- int docID;
-
- void set(Scorer scorer, Interval interval, boolean isLeaf,
- int docID) {
- this.scorer = scorer;
- this.interval.copy(interval);
- this.isLeaf = isLeaf;
- this.docID = docID;
- }
- }
-
- }
@Override
public int matchDistance() {
Index: lucene/core/src/java/org/apache/lucene/search/positions/OrderedConjunctionIntervalIterator.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/positions/OrderedConjunctionIntervalIterator.java (revision 1400508)
+++ lucene/core/src/java/org/apache/lucene/search/positions/OrderedConjunctionIntervalIterator.java (working copy)
@@ -16,10 +16,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+import org.apache.lucene.search.Scorer;
+
import java.io.IOException;
-import org.apache.lucene.search.Scorer;
-
/**
* @lucene.experimental
*/ // nocommit - javadoc
@@ -27,27 +27,20 @@
IntervalIterator {
private final IntervalIterator[] iterators;
- private static final Interval INFINITE_INTERVAL = new Interval(
- Integer.MIN_VALUE, Integer.MIN_VALUE, -1, -1);
private final Interval[] intervals;
private final int lastIter;
- private final Interval interval = new Interval(
- Integer.MAX_VALUE, Integer.MAX_VALUE, -1, -1);
+ private final Interval interval = new Interval();
+
private int index = 1;
- private int lastTopEnd;
- private int lastEndBegin;
-
-
+ private int matchDistance = 0;
+
+ private SnapshotPositionCollector snapshot = null;
+
public OrderedConjunctionIntervalIterator(boolean collectPositions, IntervalIterator other) {
- super(other.scorer, collectPositions);
- assert other.subs(true) != null;
- iterators = other.subs(true);
- assert iterators.length > 1;
- intervals = new Interval[iterators.length];
- lastIter = iterators.length - 1;
+ this(other.scorer, collectPositions, other.subs(true));
}
- public OrderedConjunctionIntervalIterator(Scorer scorer, boolean collectPositions, IntervalIterator... iterators) throws IOException {
+ public OrderedConjunctionIntervalIterator(Scorer scorer, boolean collectPositions, IntervalIterator... iterators) {
super(scorer, collectPositions);
this.iterators = iterators;
assert iterators.length > 1;
@@ -60,10 +53,7 @@
if(intervals[0] == null) {
return null;
}
- interval.begin = Integer.MAX_VALUE;
- interval.end = Integer.MAX_VALUE;
- interval.offsetBegin = -1;
- interval.offsetEnd = -1;
+ interval.setMaximum();
int b = Integer.MAX_VALUE;
while (true) {
while (true) {
@@ -84,20 +74,17 @@
} while (current.begin <= previous.end);
index++;
}
- interval.begin = intervals[0].begin;
- interval.end = intervals[lastIter].end;
- interval.offsetBegin = intervals[0].offsetBegin;
- interval.offsetEnd = intervals[lastIter].offsetEnd;
- lastTopEnd = intervals[0].end;
- lastEndBegin = intervals[lastIter].begin;
+ interval.update(intervals[0], intervals[lastIter]);
+ matchDistance = (intervals[lastIter].begin - lastIter) - intervals[0].end;
b = intervals[lastIter].begin;
index = 1;
+ if (collectPositions)
+ snapshotSubPositions();
intervals[0] = iterators[0].next();
if (intervals[0] == null) {
return interval.begin == Integer.MAX_VALUE ? null : interval;
}
}
-
}
@Override
@@ -108,10 +95,29 @@
@Override
public void collect(IntervalCollector collector) {
assert collectPositions;
+ if (snapshot == null) {
+ // we might not be initialized if the first interval matches
+ collectInternal(collector);
+ } else {
+ snapshot.replay(collector);
+ }
+ }
+
+ private void snapshotSubPositions() {
+ if (snapshot == null) {
+ snapshot = new SnapshotPositionCollector(iterators.length);
+ }
+ snapshot.reset();
+ collectInternal(snapshot);
+ }
+
+ private void collectInternal(IntervalCollector collector) {
+ assert collectPositions;
collector.collectComposite(scorer, interval, docID());
for (IntervalIterator iter : iterators) {
iter.collect(collector);
}
+
}
@Override
@@ -120,7 +126,7 @@
for (int i = 0; i < iterators.length; i++) {
int advanceTo = iterators[i].scorerAdvanced(docId);
assert advanceTo == docId;
- intervals[i] = INFINITE_INTERVAL;
+ intervals[i] = Interval.INFINITE_INTERVAL;
}
intervals[0] = iterators[0].next();
index = 1;
@@ -129,7 +135,7 @@
@Override
public int matchDistance() {
- return (lastEndBegin-lastIter) - lastTopEnd;
+ return matchDistance;
}
}
Index: lucene/core/src/java/org/apache/lucene/search/positions/IntervalFilterQuery.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/positions/IntervalFilterQuery.java (revision 1400508)
+++ lucene/core/src/java/org/apache/lucene/search/positions/IntervalFilterQuery.java (working copy)
@@ -20,9 +20,13 @@
import org.apache.lucene.index.AtomicReaderContext;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
-import org.apache.lucene.search.*;
+import org.apache.lucene.search.ComplexExplanation;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.Weight;
import org.apache.lucene.search.Weight.PostingFeatures;
-import org.apache.lucene.search.positions.IntervalIterator.IntervalCollector;
import org.apache.lucene.search.positions.IntervalIterator.IntervalFilter;
import org.apache.lucene.util.Bits;
@@ -30,15 +34,21 @@
import java.util.Set;
/**
+ * A Query that filters the results of an inner {@link Query} using an
+ * {@link IntervalFilter}.
*
* @lucene.experimental
- */ // nocommit - javadoc
+ */
public class IntervalFilterQuery extends Query implements Cloneable {
-
private Query inner;
private IntervalFilter filter;
+ /**
+ * Constructs a query using an inner query and an IntervalFilter
+ * @param inner the query to wrap
+ * @param filter the filter to restrict results by
+ */
public IntervalFilterQuery(Query inner, IntervalFilter filter) {
this.inner = inner;
this.filter = filter;
@@ -82,8 +92,8 @@
@Override
public Explanation explain(AtomicReaderContext context, int doc)
throws IOException {
- Scorer scorer = scorer(context, true, false, PostingFeatures.POSITIONS, context.reader()
- .getLiveDocs());
+ Scorer scorer = scorer(context, true, false, PostingFeatures.POSITIONS,
+ context.reader().getLiveDocs());
if (scorer != null) {
int newDoc = scorer.advance(doc);
if (newDoc == doc) {
Index: lucene/core/src/java/org/apache/lucene/search/positions/Interval.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/positions/Interval.java (revision 1400508)
+++ lucene/core/src/java/org/apache/lucene/search/positions/Interval.java (working copy)
@@ -16,65 +16,146 @@
* limitations under the License.
*/
-import java.io.IOException;
-
import org.apache.lucene.util.BytesRef;
+import java.io.IOException;
+/**
+ * Represents a section of a document that matches a query
+ */
public class Interval implements Cloneable {
-
+
+ /** The position of the start of this Interval */
public int begin;
+
+ /** The position of the end of this Interval */
public int end;
+
+ /** The offset of the start of this Interval */
public int offsetBegin;
+
+ /** The offset of the end of this Interval */
public int offsetEnd;
-
+
+ /** An interval that will always compare as less than any other interval */
+ public static final Interval INFINITE_INTERVAL = new Interval();
+
+ /**
+ * Constructs a new Interval
+ * @param begin the start position
+ * @param end the end position
+ * @param offsetBegin the start offset
+ * @param offsetEnd the end offset
+ */
public Interval(int begin, int end, int offsetBegin, int offsetEnd) {
this.begin = begin;
this.end = end;
this.offsetBegin = offsetBegin;
this.offsetEnd = offsetEnd;
}
-
+
+ /**
+ * Constructs a new Interval with no initial values. This
+ * will always compare as less than any other Interval.
+ */
public Interval() {
this(Integer.MIN_VALUE, Integer.MIN_VALUE, -1, -1);
}
-
+
+ /**
+ * Update to span the range defined by two other Intervals.
+ * @param start the first Interval
+ * @param end the second Interval
+ */
+ public void update(Interval start, Interval end) {
+ this.begin = start.begin;
+ this.offsetBegin = start.offsetBegin;
+ this.end = end.end;
+ this.offsetEnd = end.offsetEnd;
+ }
+
+ /**
+ * Compare with another Interval.
+ * @param other the comparator
+ * @return true if both start and end positions are less than
+ * the comparator.
+ */
public boolean lessThanExclusive(Interval other) {
return begin < other.begin && end < other.end;
}
-
+
+ /**
+ * Compare with another Interval.
+ * @param other the comparator
+ * @return true if both start and end positions are less than
+ * or equal to the comparator's.
+ */
public boolean lessThan(Interval other) {
return begin <= other.begin && end <= other.end;
}
-
+
+ /**
+ * Compare with another Interval
+ * @param other the comparator
+ * @return true if both start and end positions are greater then
+ * the comparator's.
+ */
public boolean greaterThanExclusive(Interval other) {
return begin > other.begin && end > other.end;
}
-
+
+ /**
+ * Compare with another Interval
+ * @param other the comparator
+ * @return true if both start and end positions are greater then
+ * of equal to the comparator's.
+ */
public boolean greaterThan(Interval other) {
return begin >= other.begin && end >= other.end;
}
-
+
+ /**
+ * Compare with another Interval
+ * @param other the comparator
+ * @return true if this Interval contains the comparator
+ */
public boolean contains(Interval other) {
return begin <= other.begin && other.end <= end;
}
-
+
+ /**
+ * Set all values of this Interval to be equal to another's
+ * @param other the Interval to copy
+ */
public void copy(Interval other) {
begin = other.begin;
end = other.end;
offsetBegin = other.offsetBegin;
offsetEnd = other.offsetEnd;
}
-
+
+ // nocommit javadocs
public BytesRef nextPayload() throws IOException {
return null;
}
-
-
+
+ /**
+ * Set to a state that will always compare as less than any
+ * other Interval.
+ */
public void reset() {
offsetBegin = offsetEnd = -1;
begin = end = Integer.MIN_VALUE;
}
+
+ /**
+ * Set to a state that will always compare as more than any
+ * other Interval.
+ */
+ public void setMaximum() {
+ offsetBegin = offsetEnd = -1;
+ begin = end = Integer.MAX_VALUE;
+ }
@Override
public Object clone() {
@@ -90,5 +171,5 @@
return "Interval [begin=" + begin + "(" + offsetBegin + "), end="
+ end + "(" + offsetEnd + ")]";
}
-
+
}
\ No newline at end of file
Index: lucene/core/src/java/org/apache/lucene/search/positions/SnapshotPositionCollector.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/positions/SnapshotPositionCollector.java (revision 0)
+++ lucene/core/src/java/org/apache/lucene/search/positions/SnapshotPositionCollector.java (revision 0)
@@ -0,0 +1,107 @@
+package org.apache.lucene.search.positions;
+
+/*
+ * 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.Scorer;
+import org.apache.lucene.util.ArrayUtil;
+import org.apache.lucene.util.RamUsageEstimator;
+
+/*
+ * Due to the laziness of Conjunction position iterators and the minimizing algorithm
+ * we advance the underlying iterators before the consumer can call collect on
+ * the top level iterator. If we need to collect positions we need to record
+ * the last possible match in order to allow the consumer to get the right
+ * positions for the match. This is particularly important if leaf positions
+ * are required.
+ */
+final class SnapshotPositionCollector implements
+ IntervalIterator.IntervalCollector {
+ private SingleSnapshot[] snapshots;
+ private int index = 0;
+
+ SnapshotPositionCollector(int subs) {
+ snapshots = new SingleSnapshot[subs];
+ }
+
+ @Override
+ public void collectLeafPosition(Scorer scorer, Interval interval,
+ int docID) {
+ collect(scorer, interval, docID, true);
+
+ }
+
+ private void collect(Scorer scorer, Interval interval, int docID,
+ boolean isLeaf) {
+ if (snapshots.length <= index) {
+ grow(ArrayUtil.oversize(index + 1,
+ (RamUsageEstimator.NUM_BYTES_OBJECT_REF * 2)
+ + RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
+ + RamUsageEstimator.NUM_BYTES_BOOLEAN
+ + RamUsageEstimator.NUM_BYTES_INT));
+ }
+ if (snapshots[index] == null) {
+ snapshots[index] = new SingleSnapshot();
+ }
+ snapshots[index++].set(scorer, interval, isLeaf, docID);
+ }
+
+ @Override
+ public void collectComposite(Scorer scorer, Interval interval,
+ int docID) {
+ collect(scorer, interval, docID, false);
+ }
+
+ void replay(IntervalIterator.IntervalCollector collector) {
+ for (int i = 0; i < index; i++) {
+ SingleSnapshot singleSnapshot = snapshots[i];
+ if (singleSnapshot.isLeaf) {
+ collector.collectLeafPosition(singleSnapshot.scorer,
+ singleSnapshot.interval, singleSnapshot.docID);
+ } else {
+ collector.collectComposite(singleSnapshot.scorer,
+ singleSnapshot.interval, singleSnapshot.docID);
+ }
+ }
+ }
+
+ void reset() {
+ index = 0;
+ }
+
+ private void grow(int size) {
+ final SingleSnapshot[] newArray = new SingleSnapshot[size];
+ System.arraycopy(snapshots, 0, newArray, 0, index);
+ snapshots = newArray;
+ }
+
+ private static final class SingleSnapshot {
+ Scorer scorer;
+ final Interval interval = new Interval();
+ boolean isLeaf;
+ int docID;
+
+ void set(Scorer scorer, Interval interval, boolean isLeaf,
+ int docID) {
+ this.scorer = scorer;
+ this.interval.copy(interval);
+ this.isLeaf = isLeaf;
+ this.docID = docID;
+ }
+ }
+
+}
Index: lucene/core/src/java/org/apache/lucene/search/positions/IntervalIterator.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/positions/IntervalIterator.java (revision 1400508)
+++ lucene/core/src/java/org/apache/lucene/search/positions/IntervalIterator.java (working copy)
@@ -30,7 +30,7 @@
public static final IntervalIterator[] EMPTY = new IntervalIterator[0];
public static final IntervalIterator NO_MORE_POSITIONS = new EmptyIntervalIterator();
public static final int NO_MORE_DOCS = Integer.MAX_VALUE;
-
+
protected final Scorer scorer;
protected final boolean collectPositions;
@@ -38,11 +38,29 @@
this.scorer = scorer;
this.collectPositions = collectPositions;
}
-
+
+ /**
+ * Called after the parent scorer has been advanced. If the scorer is
+ * currently positioned on docId, then subsequent calls to next() will
+ * return Intervals for that document; otherwise, no Intervals are
+ * available
+ * @param docId the document the parent scorer was advanced to
+ * @return the docId that the scorer is currently positioned at
+ * @throws IOException if a low-level I/O error is encountered
+ */
public abstract int scorerAdvanced(int docId) throws IOException;
-
+
+ /**
+ * Get the next Interval on the current document.
+ * @return the next Interval, or null if there are no remaining Intervals
+ * @throws IOException if a low-level I/O error is encountered
+ */
public abstract Interval next() throws IOException;
-
+
+ /**
+ * Called once for each positional match on a document
+ * @param collector
+ */
public abstract void collect(IntervalCollector collector);
public abstract IntervalIterator[] subs(boolean inOrder);
Index: lucene/core/src/java/org/apache/lucene/search/Scorer.java
===================================================================
--- lucene/core/src/java/org/apache/lucene/search/Scorer.java (revision 1400508)
+++ lucene/core/src/java/org/apache/lucene/search/Scorer.java (working copy)
@@ -64,8 +64,14 @@
collector.collect(doc);
}
}
-
- //nocommit javadocs
+
+ /**
+ * Expert: Collects matching positions on the current document.
+ *
+ * @param collectPositions // nocommit, still not sure what this does!
+ * @return an {@link IntervalIterator} over matching positions
+ * @throws IOException if a low-level I/O error is encountered
+ */
public abstract IntervalIterator positions(boolean collectPositions) throws IOException;
/**
Index: lucene/highlighter/src/test/org/apache/lucene/search/highlight/positions/IntervalHighlighterTest.java
===================================================================
--- lucene/highlighter/src/test/org/apache/lucene/search/highlight/positions/IntervalHighlighterTest.java (revision 1400508)
+++ lucene/highlighter/src/test/org/apache/lucene/search/highlight/positions/IntervalHighlighterTest.java (working copy)
@@ -34,21 +34,27 @@
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.index.Term;
-import org.apache.lucene.search.*;
+import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanClause.Occur;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.ConstantScoreQuery;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.MultiPhraseQuery;
+import org.apache.lucene.search.MultiTermQuery;
+import org.apache.lucene.search.PhraseQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.WildcardQuery;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;
import org.apache.lucene.search.highlight.SimpleFragmenter;
import org.apache.lucene.search.highlight.TextFragment;
-import org.apache.lucene.search.highlight.positions.HighlightingIntervalCollector;
-import org.apache.lucene.search.highlight.positions.IntervalTokenStream;
-import org.apache.lucene.search.highlight.positions.ArrayIntervalIterator;
-import org.apache.lucene.search.highlight.positions.DocAndPositions;
import org.apache.lucene.search.positions.BlockIntervalIterator;
import org.apache.lucene.search.positions.BrouwerianQuery;
import org.apache.lucene.search.positions.IntervalFilterQuery;
import org.apache.lucene.search.positions.IntervalIterator;
import org.apache.lucene.search.positions.IntervalIterator.IntervalFilter;
+import org.apache.lucene.search.positions.OrderedConjunctionQuery;
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.LuceneTestCase;
import org.apache.lucene.util._TestUtil;
@@ -122,6 +128,10 @@
}
searcher = new IndexSearcher(DirectoryReader.open(dir));
}
+
+ protected static TermQuery termQuery(String term) {
+ return new TermQuery(new Term(F, term));
+ }
private String[] doSearch(Query q) throws IOException,
InvalidTokenOffsetsException {
@@ -195,7 +205,7 @@
public void testTerm() throws Exception {
insertDocs(analyzer, "This is a test test");
- String frags[] = doSearch(new TermQuery(new Term(F, "test")));
+ String frags[] = doSearch(termQuery("test"));
assertEquals("This is a test test", frags[0]);
close();
}
@@ -206,8 +216,7 @@
String gold = "this is some long text. It has the word long in many places. In fact, it has long on some different fragments. "
+ "Let us see what happens to long in this case.";
insertDocs(analyzer, input);
- String frags[] = doSearch(new TermQuery(new Term(F, "long")),
- input.length());
+ String frags[] = doSearch(termQuery("long"), input.length());
assertEquals(gold, frags[0]);
close();
}
@@ -215,8 +224,8 @@
public void testBooleanAnd() throws Exception {
insertDocs(analyzer, "This is a test");
BooleanQuery bq = new BooleanQuery();
- bq.add(new BooleanClause(new TermQuery(new Term(F, "This")), Occur.MUST));
- bq.add(new BooleanClause(new TermQuery(new Term(F, "test")), Occur.MUST));
+ bq.add(new BooleanClause(termQuery("This"), Occur.MUST));
+ bq.add(new BooleanClause(termQuery("test"), Occur.MUST));
String frags[] = doSearch(bq);
assertEquals("This is a test", frags[0]);
close();
@@ -225,8 +234,8 @@
public void testConstantScore() throws Exception {
insertDocs(analyzer, "This is a test");
BooleanQuery bq = new BooleanQuery();
- bq.add(new BooleanClause(new TermQuery(new Term(F, "This")), Occur.MUST));
- bq.add(new BooleanClause(new TermQuery(new Term(F, "test")), Occur.MUST));
+ bq.add(new BooleanClause(termQuery("This"), Occur.MUST));
+ bq.add(new BooleanClause(termQuery("test"), Occur.MUST));
String frags[] = doSearch(new ConstantScoreQuery(bq));
assertEquals("This is a test", frags[0]);
close();
@@ -443,8 +452,30 @@
close();
}
-
- private Term[] terms(String field, String...tokens) {
+
+ public void testNearPhraseQuery() throws Exception {
+
+ insertDocs(analyzer, "pease porridge rather hot and pease porridge fairly cold");
+
+ Query firstQ = new OrderedConjunctionQuery(4, termQuery("pease"), termQuery("porridge"), termQuery("hot"));
+ {
+ String frags[] = doSearch(firstQ, Integer.MAX_VALUE);
+ assertEquals("pease porridge rather hot and pease porridge fairly cold", frags[0]);
+ }
+
+ // near.3(near.4(pease, porridge, hot), near.4(pease, porridge, cold))
+ Query q = new OrderedConjunctionQuery(3,
+ firstQ,
+ new OrderedConjunctionQuery(4, termQuery("pease"), termQuery("porridge"), termQuery("cold")));
+
+ String frags[] = doSearch(q, Integer.MAX_VALUE);
+ assertEquals("pease porridge rather hot and pease porridge fairly cold",
+ frags[0]);
+
+ close();
+ }
+
+ private Term[] terms(String field, String...tokens) {
Term[] terms = new Term[tokens.length];
for (int i = 0; i < tokens.length; i++) {
terms[i] = new Term(field, tokens[i]);
@@ -474,7 +505,8 @@
assertSloppyPhrase( "A A X A Y B A", null , 1, "X", "A", "A");
close();
}
-
+
+
private void assertSloppyPhrase(String doc, String expected, int slop, String...query) throws Exception {
insertDocs(analyzer, doc);
PhraseQuery pq = new PhraseQuery();