mirror of https://github.com/apache/lucene.git
LUCENE-2692: add some new SpanQuery classes
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1021357 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
76c371d5d7
commit
8887a044ea
|
@ -261,6 +261,9 @@ New features
|
|||
pretend it's an atomic reader. This is a convenience class (you can
|
||||
use MultiFields static methods directly, instead) if you need to use
|
||||
the flex APIs directly on a composite reader. (Mike McCandless)
|
||||
|
||||
* LUCENE-2692: Added several new SpanQuery classes for positional checking
|
||||
(match is in a range, payload is a specific value) (Grant Ingersoll)
|
||||
|
||||
Optimizations
|
||||
|
||||
|
|
|
@ -17,37 +17,30 @@ package org.apache.lucene.search.spans;
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.util.ToStringUtils;
|
||||
|
||||
/** Matches spans near the beginning of a field. */
|
||||
public class SpanFirstQuery extends SpanQuery implements Cloneable {
|
||||
private SpanQuery match;
|
||||
private int end;
|
||||
import java.io.IOException;
|
||||
|
||||
/** Matches spans near the beginning of a field.
|
||||
* <p/>
|
||||
* This class is a simple extension of {@link SpanPositionRangeQuery} in that it assumes the
|
||||
* start to be zero and only checks the end boundary.
|
||||
*
|
||||
*
|
||||
* */
|
||||
public class SpanFirstQuery extends SpanPositionRangeQuery {
|
||||
|
||||
/** Construct a SpanFirstQuery matching spans in <code>match</code> whose end
|
||||
* position is less than or equal to <code>end</code>. */
|
||||
public SpanFirstQuery(SpanQuery match, int end) {
|
||||
this.match = match;
|
||||
this.end = end;
|
||||
super(match, 0, end);
|
||||
}
|
||||
|
||||
/** Return the SpanQuery whose matches are filtered. */
|
||||
public SpanQuery getMatch() { return match; }
|
||||
|
||||
/** Return the maximum end position permitted in a match. */
|
||||
public int getEnd() { return end; }
|
||||
|
||||
@Override
|
||||
public String getField() { return match.getField(); }
|
||||
protected boolean acceptPosition(Spans spans) throws IOException {
|
||||
return spans.end() <= end;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString(String field) {
|
||||
|
@ -60,89 +53,13 @@ public class SpanFirstQuery extends SpanQuery implements Cloneable {
|
|||
buffer.append(ToStringUtils.boost(getBoost()));
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
SpanFirstQuery spanFirstQuery = new SpanFirstQuery((SpanQuery) match.clone(), end);
|
||||
spanFirstQuery.setBoost(getBoost());
|
||||
return spanFirstQuery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void extractTerms(Set<Term> terms) {
|
||||
match.extractTerms(terms);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spans getSpans(final IndexReader reader) throws IOException {
|
||||
return new Spans() {
|
||||
private Spans spans = match.getSpans(reader);
|
||||
|
||||
@Override
|
||||
public boolean next() throws IOException {
|
||||
while (spans.next()) { // scan to next match
|
||||
if (end() <= end)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
if (!spans.skipTo(target))
|
||||
return false;
|
||||
|
||||
return spans.end() <= end || next();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int doc() { return spans.doc(); }
|
||||
@Override
|
||||
public int start() { return spans.start(); }
|
||||
@Override
|
||||
public int end() { return spans.end(); }
|
||||
|
||||
// TODO: Remove warning after API has been finalized
|
||||
@Override
|
||||
public Collection<byte[]> getPayload() throws IOException {
|
||||
ArrayList<byte[]> result = null;
|
||||
if (spans.isPayloadAvailable()) {
|
||||
result = new ArrayList<byte[]>(spans.getPayload());
|
||||
}
|
||||
return result;//TODO: any way to avoid the new construction?
|
||||
}
|
||||
|
||||
// TODO: Remove warning after API has been finalized
|
||||
@Override
|
||||
public boolean isPayloadAvailable() {
|
||||
return spans.isPayloadAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "spans(" + SpanFirstQuery.this.toString() + ")";
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query rewrite(IndexReader reader) throws IOException {
|
||||
SpanFirstQuery clone = null;
|
||||
|
||||
SpanQuery rewritten = (SpanQuery) match.rewrite(reader);
|
||||
if (rewritten != match) {
|
||||
clone = (SpanFirstQuery) this.clone();
|
||||
clone.match = rewritten;
|
||||
}
|
||||
|
||||
if (clone != null) {
|
||||
return clone; // some clauses rewrote
|
||||
} else {
|
||||
return this; // no clauses rewrote
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
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 org.apache.lucene.util.ToStringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* Only return those matches that have a specific payload at
|
||||
* the given position.
|
||||
* <p/>
|
||||
*
|
||||
*/
|
||||
public class SpanNearPayloadCheckQuery extends SpanPositionCheckQuery {
|
||||
protected final Collection<byte[]> payloadToMatch;
|
||||
|
||||
/**
|
||||
* @param match The underlying {@link SpanQuery} to check
|
||||
* @param payloadToMatch The {@link java.util.Collection} of payloads to match
|
||||
*/
|
||||
public SpanNearPayloadCheckQuery(SpanNearQuery match, Collection<byte[]> payloadToMatch) {
|
||||
super(match);
|
||||
this.payloadToMatch = payloadToMatch;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean acceptPosition(Spans spans) throws IOException {
|
||||
boolean result = spans.isPayloadAvailable();
|
||||
if (result == true) {
|
||||
Collection<byte[]> candidate = spans.getPayload();
|
||||
if (candidate.size() == payloadToMatch.size()) {
|
||||
//TODO: check the byte arrays are the same
|
||||
//hmm, can't rely on order here
|
||||
int matches = 0;
|
||||
for (byte[] candBytes : candidate) {
|
||||
//Unfortunately, we can't rely on order, so we need to compare all
|
||||
for (byte[] payBytes : payloadToMatch) {
|
||||
if (Arrays.equals(candBytes, payBytes) == true) {
|
||||
matches++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (matches == payloadToMatch.size()){
|
||||
//we've verified all the bytes
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString(String field) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.append("spanPayCheck(");
|
||||
buffer.append(match.toString(field));
|
||||
buffer.append(", payloadRef: ");
|
||||
for (byte[] bytes : payloadToMatch) {
|
||||
ToStringUtils.byteArray(buffer, bytes);
|
||||
buffer.append(';');
|
||||
}
|
||||
buffer.append(")");
|
||||
buffer.append(ToStringUtils.boost(getBoost()));
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
SpanNearPayloadCheckQuery result = new SpanNearPayloadCheckQuery((SpanNearQuery) match.clone(), payloadToMatch);
|
||||
result.setBoost(getBoost());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof SpanNearPayloadCheckQuery)) return false;
|
||||
|
||||
SpanNearPayloadCheckQuery other = (SpanNearPayloadCheckQuery) o;
|
||||
return this.payloadToMatch.equals(other.payloadToMatch)
|
||||
&& this.match.equals(other.match)
|
||||
&& this.getBoost() == other.getBoost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = match.hashCode();
|
||||
h ^= (h << 8) | (h >>> 25); // reversible
|
||||
//TODO: is this right?
|
||||
h ^= payloadToMatch.hashCode();
|
||||
h ^= Float.floatToRawIntBits(getBoost());
|
||||
return h;
|
||||
}
|
||||
}
|
|
@ -45,7 +45,11 @@ public class SpanNearQuery extends SpanQuery implements Cloneable {
|
|||
/** Construct a SpanNearQuery. Matches spans matching a span from each
|
||||
* clause, with up to <code>slop</code> total unmatched positions between
|
||||
* them. * When <code>inOrder</code> is true, the spans from each clause
|
||||
* must be * ordered as in <code>clauses</code>. */
|
||||
* must be * ordered as in <code>clauses</code>.
|
||||
* @param clauses the clauses to find near each other
|
||||
* @param slop The slop value
|
||||
* @param inOrder true if order is important
|
||||
* */
|
||||
public SpanNearQuery(SpanQuery[] clauses, int slop, boolean inOrder) {
|
||||
this(clauses, slop, inOrder, true);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
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 org.apache.lucene.util.ToStringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* Only return those matches that have a specific payload at
|
||||
* the given position.
|
||||
*<p/>
|
||||
* Do not use this with an SpanQuery that contains a {@link org.apache.lucene.search.spans.SpanNearQuery}. Instead, use
|
||||
* {@link SpanNearPayloadCheckQuery} since it properly handles the fact that payloads
|
||||
* aren't ordered by {@link org.apache.lucene.search.spans.SpanNearQuery}.
|
||||
*
|
||||
**/
|
||||
public class SpanPayloadCheckQuery extends SpanPositionCheckQuery{
|
||||
protected final Collection<byte[]> payloadToMatch;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param match The underlying {@link org.apache.lucene.search.spans.SpanQuery} to check
|
||||
* @param payloadToMatch The {@link java.util.Collection} of payloads to match
|
||||
*/
|
||||
public SpanPayloadCheckQuery(SpanQuery match, Collection<byte[]> payloadToMatch) {
|
||||
super(match);
|
||||
if (match instanceof SpanNearQuery){
|
||||
throw new IllegalArgumentException("SpanNearQuery not allowed");
|
||||
}
|
||||
this.payloadToMatch = payloadToMatch;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean acceptPosition(Spans spans) throws IOException {
|
||||
boolean result = spans.isPayloadAvailable();
|
||||
if (result == true){
|
||||
Collection<byte[]> candidate = spans.getPayload();
|
||||
if (candidate.size() == payloadToMatch.size()){
|
||||
//TODO: check the byte arrays are the same
|
||||
Iterator<byte[]> toMatchIter = payloadToMatch.iterator();
|
||||
//check each of the byte arrays, in order
|
||||
//hmm, can't rely on order here
|
||||
for (byte[] candBytes : candidate) {
|
||||
//if one is a mismatch, then return false
|
||||
if (Arrays.equals(candBytes, toMatchIter.next()) == false){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//we've verified all the bytes
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toString(String field) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.append("spanPayCheck(");
|
||||
buffer.append(match.toString(field));
|
||||
buffer.append(", payloadRef: ");
|
||||
for (byte[] bytes : payloadToMatch) {
|
||||
ToStringUtils.byteArray(buffer, bytes);
|
||||
buffer.append(';');
|
||||
}
|
||||
buffer.append(")");
|
||||
buffer.append(ToStringUtils.boost(getBoost()));
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
SpanPayloadCheckQuery result = new SpanPayloadCheckQuery((SpanQuery) match.clone(), payloadToMatch);
|
||||
result.setBoost(getBoost());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof SpanPayloadCheckQuery)) return false;
|
||||
|
||||
SpanPayloadCheckQuery other = (SpanPayloadCheckQuery)o;
|
||||
return this.payloadToMatch.equals(other.payloadToMatch)
|
||||
&& this.match.equals(other.match)
|
||||
&& this.getBoost() == other.getBoost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = match.hashCode();
|
||||
h ^= (h << 8) | (h >>> 25); // reversible
|
||||
//TODO: is this right?
|
||||
h ^= payloadToMatch.hashCode();
|
||||
h ^= Float.floatToRawIntBits(getBoost()) ;
|
||||
return h;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
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 org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.Query;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
**/
|
||||
public abstract class SpanPositionCheckQuery extends SpanQuery implements Cloneable {
|
||||
protected SpanQuery match;
|
||||
|
||||
|
||||
public SpanPositionCheckQuery(SpanQuery match) {
|
||||
this.match = match;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the SpanQuery whose matches are filtered.
|
||||
*
|
||||
* */
|
||||
public SpanQuery getMatch() { return match; }
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getField() { return match.getField(); }
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void extractTerms(Set<Term> terms) {
|
||||
match.extractTerms(terms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementing classes are required to return whether the current position is a match for the passed in
|
||||
* "match" {@link org.apache.lucene.search.spans.SpanQuery}.
|
||||
*
|
||||
* This is only called if the underlying {@link org.apache.lucene.search.spans.Spans#next()} for the
|
||||
* match is successful
|
||||
*
|
||||
*
|
||||
* @param spans The {@link org.apache.lucene.search.spans.Spans} instance, positioned at the spot to check
|
||||
* @return true if it is a match, else false.
|
||||
*
|
||||
* @see org.apache.lucene.search.spans.Spans#next()
|
||||
*
|
||||
*/
|
||||
protected abstract boolean acceptPosition(Spans spans) throws IOException;
|
||||
|
||||
/**
|
||||
* Implementing classes are required to return whether the position at the target is someplace that
|
||||
* can be skipped to. For instance, the {@link org.apache.lucene.search.spans.SpanFirstQuery} returns
|
||||
* false if the target position is beyond the maximum position allowed or if {@link Spans#next()} is true.
|
||||
* <p/>
|
||||
* Note, this method is only called if the underlying match {@link org.apache.lucene.search.spans.SpanQuery} can
|
||||
* skip to the target.
|
||||
* <p/>
|
||||
* It is safe to assume that the passed in {@link org.apache.lucene.search.spans.Spans} object for the underlying {@link org.apache.lucene.search.spans.SpanQuery} is
|
||||
* positioned at the target.
|
||||
* <p/>
|
||||
* The default implementation is to return true if either {@link #acceptPosition(Spans)} or {@link org.apache.lucene.search.spans.Spans#next()} is true for the
|
||||
* passed in instance of Spans.
|
||||
*<p/>
|
||||
* @param spans The {@link org.apache.lucene.search.spans.Spans} to check
|
||||
* @return true if the instance can skip to this position
|
||||
*
|
||||
* @see Spans#skipTo(int)
|
||||
* @throws java.io.IOException if there is a low-level IO error
|
||||
*/
|
||||
protected boolean acceptSkipTo(Spans spans) throws IOException{
|
||||
return acceptPosition(spans) || spans.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spans getSpans(final IndexReader reader) throws IOException {
|
||||
return new PositionCheckSpan(reader);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Query rewrite(IndexReader reader) throws IOException {
|
||||
SpanPositionCheckQuery clone = null;
|
||||
|
||||
SpanQuery rewritten = (SpanQuery) match.rewrite(reader);
|
||||
if (rewritten != match) {
|
||||
clone = (SpanPositionCheckQuery) this.clone();
|
||||
clone.match = rewritten;
|
||||
}
|
||||
|
||||
if (clone != null) {
|
||||
return clone; // some clauses rewrote
|
||||
} else {
|
||||
return this; // no clauses rewrote
|
||||
}
|
||||
}
|
||||
|
||||
protected class PositionCheckSpan extends Spans {
|
||||
private Spans spans;
|
||||
|
||||
private final IndexReader reader;
|
||||
|
||||
public PositionCheckSpan(IndexReader reader) throws IOException {
|
||||
this.reader = reader;
|
||||
spans = match.getSpans(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean next() throws IOException {
|
||||
//TODO: optimize to skip ahead to start
|
||||
while (spans.next()) { // scan to next match
|
||||
if (acceptPosition(this))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean skipTo(int target) throws IOException {
|
||||
if (!spans.skipTo(target))
|
||||
return false;
|
||||
|
||||
return acceptSkipTo(this);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int doc() { return spans.doc(); }
|
||||
|
||||
@Override
|
||||
public int start() { return spans.start(); }
|
||||
|
||||
@Override
|
||||
public int end() { return spans.end(); }
|
||||
// TODO: Remove warning after API has been finalized
|
||||
|
||||
@Override
|
||||
public Collection<byte[]> getPayload() throws IOException {
|
||||
ArrayList<byte[]> result = null;
|
||||
if (spans.isPayloadAvailable()) {
|
||||
result = new ArrayList<byte[]>(spans.getPayload());
|
||||
}
|
||||
return result;//TODO: any way to avoid the new construction?
|
||||
}
|
||||
// TODO: Remove warning after API has been finalized
|
||||
|
||||
@Override
|
||||
public boolean isPayloadAvailable() {
|
||||
return spans.isPayloadAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "spans(" + SpanPositionCheckQuery.this.toString() + ")";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
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 org.apache.lucene.util.ToStringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
/**
|
||||
* Checks to see if the {@link #getMatch()} lies between a start and end position
|
||||
*
|
||||
* @see org.apache.lucene.search.spans.SpanFirstQuery for a derivation that is optimized for the case where start position is 0
|
||||
*/
|
||||
public class SpanPositionRangeQuery extends SpanPositionCheckQuery {
|
||||
protected int start = 0;
|
||||
protected int end;
|
||||
|
||||
public SpanPositionRangeQuery(SpanQuery match, int start, int end) {
|
||||
super(match);
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean acceptPosition(Spans spans) throws IOException {
|
||||
return spans.start() >= start && spans.end() <= end;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return The minimum position permitted in a match
|
||||
*/
|
||||
public int getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the maximum end position permitted in a match.
|
||||
*/
|
||||
public int getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(String field) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.append("spanPosRange(");
|
||||
buffer.append(match.toString(field));
|
||||
buffer.append(", ").append(start).append(", ");
|
||||
buffer.append(end);
|
||||
buffer.append(")");
|
||||
buffer.append(ToStringUtils.boost(getBoost()));
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
SpanPositionRangeQuery result = new SpanPositionRangeQuery((SpanQuery) match.clone(), start, end);
|
||||
result.setBoost(getBoost());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof SpanPositionRangeQuery)) return false;
|
||||
|
||||
SpanPositionRangeQuery other = (SpanPositionRangeQuery)o;
|
||||
return this.end == other.end && this.start == other.start
|
||||
&& this.match.equals(other.match)
|
||||
&& this.getBoost() == other.getBoost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = match.hashCode();
|
||||
h ^= (h << 8) | (h >>> 25); // reversible
|
||||
h ^= Float.floatToRawIntBits(getBoost()) ^ end ^ start;
|
||||
return h;
|
||||
}
|
||||
|
||||
}
|
|
@ -21,11 +21,23 @@ package org.apache.lucene.util;
|
|||
* Helper methods to ease implementing {@link Object#toString()}.
|
||||
*/
|
||||
public class ToStringUtils {
|
||||
/** for printing boost only if not 1.0 */
|
||||
/**
|
||||
* for printing boost only if not 1.0
|
||||
*/
|
||||
public static String boost(float boost) {
|
||||
if (boost != 1.0f) {
|
||||
return "^" + Float.toString(boost);
|
||||
} else return "";
|
||||
}
|
||||
|
||||
public static void byteArray(StringBuilder buffer, byte[] bytes) {
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
buffer.append("b[").append(i).append("]=").append(bytes[i]);
|
||||
if (i < bytes.length - 1) {
|
||||
buffer.append(',');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,10 @@ package org.apache.lucene.analysis;
|
|||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
|
||||
import org.apache.lucene.analysis.tokenattributes.PayloadAttribute;
|
||||
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
|
||||
import org.apache.lucene.index.Payload;
|
||||
import org.apache.lucene.util.automaton.CharacterRunAutomaton;
|
||||
|
||||
/**
|
||||
|
@ -30,8 +34,13 @@ public final class MockAnalyzer extends Analyzer {
|
|||
private final boolean lowerCase;
|
||||
private final CharacterRunAutomaton filter;
|
||||
private final boolean enablePositionIncrements;
|
||||
private final boolean payload;
|
||||
private int positionIncrementGap;
|
||||
|
||||
public MockAnalyzer(CharacterRunAutomaton runAutomaton, boolean lowerCase, CharacterRunAutomaton filter, boolean enablePositionIncrements) {
|
||||
this(runAutomaton, lowerCase, filter, enablePositionIncrements, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new MockAnalyzer.
|
||||
*
|
||||
|
@ -39,12 +48,14 @@ public final class MockAnalyzer extends Analyzer {
|
|||
* @param lowerCase true if the tokenizer should lowercase terms
|
||||
* @param filter DFA describing how terms should be filtered (set of stopwords, etc)
|
||||
* @param enablePositionIncrements true if position increments should reflect filtered terms.
|
||||
* @param payload if payloads should be added
|
||||
*/
|
||||
public MockAnalyzer(CharacterRunAutomaton runAutomaton, boolean lowerCase, CharacterRunAutomaton filter, boolean enablePositionIncrements) {
|
||||
public MockAnalyzer(CharacterRunAutomaton runAutomaton, boolean lowerCase, CharacterRunAutomaton filter, boolean enablePositionIncrements, boolean payload) {
|
||||
this.runAutomaton = runAutomaton;
|
||||
this.lowerCase = lowerCase;
|
||||
this.filter = filter;
|
||||
this.enablePositionIncrements = enablePositionIncrements;
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -54,7 +65,11 @@ public final class MockAnalyzer extends Analyzer {
|
|||
* @param lowerCase true if the tokenizer should lowercase terms
|
||||
*/
|
||||
public MockAnalyzer(CharacterRunAutomaton runAutomaton, boolean lowerCase) {
|
||||
this(runAutomaton, lowerCase, MockTokenFilter.EMPTY_STOPSET, false);
|
||||
this(runAutomaton, lowerCase, MockTokenFilter.EMPTY_STOPSET, false, false);
|
||||
}
|
||||
|
||||
public MockAnalyzer(CharacterRunAutomaton runAutomaton, boolean lowerCase, boolean payload) {
|
||||
this(runAutomaton, lowerCase, MockTokenFilter.EMPTY_STOPSET, false, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,12 +82,16 @@ public final class MockAnalyzer extends Analyzer {
|
|||
@Override
|
||||
public TokenStream tokenStream(String fieldName, Reader reader) {
|
||||
MockTokenizer tokenizer = new MockTokenizer(reader, runAutomaton, lowerCase);
|
||||
return new MockTokenFilter(tokenizer, filter, enablePositionIncrements);
|
||||
TokenFilter filt = new MockTokenFilter(tokenizer, filter, enablePositionIncrements);
|
||||
if (payload){
|
||||
filt = new SimplePayloadFilter(filt, fieldName);
|
||||
}
|
||||
return filt;
|
||||
}
|
||||
|
||||
private class SavedStreams {
|
||||
MockTokenizer tokenizer;
|
||||
MockTokenFilter filter;
|
||||
TokenFilter filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -83,10 +102,14 @@ public final class MockAnalyzer extends Analyzer {
|
|||
saved = new SavedStreams();
|
||||
saved.tokenizer = new MockTokenizer(reader, runAutomaton, lowerCase);
|
||||
saved.filter = new MockTokenFilter(saved.tokenizer, filter, enablePositionIncrements);
|
||||
if (payload){
|
||||
saved.filter = new SimplePayloadFilter(saved.filter, fieldName);
|
||||
}
|
||||
setPreviousTokenStream(saved);
|
||||
return saved.filter;
|
||||
} else {
|
||||
saved.tokenizer.reset(reader);
|
||||
saved.filter.reset();
|
||||
return saved.filter;
|
||||
}
|
||||
}
|
||||
|
@ -99,4 +122,30 @@ public final class MockAnalyzer extends Analyzer {
|
|||
public int getPositionIncrementGap(String fieldName){
|
||||
return positionIncrementGap;
|
||||
}
|
||||
}
|
||||
|
||||
final class SimplePayloadFilter extends TokenFilter {
|
||||
String fieldName;
|
||||
int pos;
|
||||
final PayloadAttribute payloadAttr;
|
||||
final CharTermAttribute termAttr;
|
||||
|
||||
public SimplePayloadFilter(TokenStream input, String fieldName) {
|
||||
super(input);
|
||||
this.fieldName = fieldName;
|
||||
pos = 0;
|
||||
payloadAttr = input.addAttribute(PayloadAttribute.class);
|
||||
termAttr = input.addAttribute(CharTermAttribute.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean incrementToken() throws IOException {
|
||||
if (input.incrementToken()) {
|
||||
payloadAttr.setPayload(new Payload(("pos: " + pos).getBytes()));
|
||||
pos++;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package org.apache.lucene.analysis;
|
||||
/**
|
||||
* 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.analysis.tokenattributes.CharTermAttribute;
|
||||
import org.apache.lucene.analysis.tokenattributes.PayloadAttribute;
|
||||
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
|
||||
import org.apache.lucene.index.Payload;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
**/
|
||||
public final class MockPayloadAnalyzer extends Analyzer {
|
||||
|
||||
@Override
|
||||
public TokenStream tokenStream(String fieldName, Reader reader) {
|
||||
TokenStream result = new MockTokenizer(reader, MockTokenizer.WHITESPACE, true);
|
||||
return new MockPayloadFilter(result, fieldName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
**/
|
||||
final class MockPayloadFilter extends TokenFilter {
|
||||
String fieldName;
|
||||
|
||||
int pos;
|
||||
|
||||
int i;
|
||||
|
||||
final PositionIncrementAttribute posIncrAttr;
|
||||
final PayloadAttribute payloadAttr;
|
||||
final CharTermAttribute termAttr;
|
||||
|
||||
public MockPayloadFilter(TokenStream input, String fieldName) {
|
||||
super(input);
|
||||
this.fieldName = fieldName;
|
||||
pos = 0;
|
||||
i = 0;
|
||||
posIncrAttr = input.addAttribute(PositionIncrementAttribute.class);
|
||||
payloadAttr = input.addAttribute(PayloadAttribute.class);
|
||||
termAttr = input.addAttribute(CharTermAttribute.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean incrementToken() throws IOException {
|
||||
if (input.incrementToken()) {
|
||||
payloadAttr.setPayload(new Payload(("pos: " + pos).getBytes()));
|
||||
int posIncr;
|
||||
if (i % 2 == 1) {
|
||||
posIncr = 1;
|
||||
} else {
|
||||
posIncr = 0;
|
||||
}
|
||||
posIncrAttr.setPositionIncrement(posIncr);
|
||||
pos += posIncr;
|
||||
i++;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() throws IOException {
|
||||
i = 0;
|
||||
pos = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -18,18 +18,16 @@ package org.apache.lucene.search;
|
|||
*/
|
||||
|
||||
import java.io.Reader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.Collection;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.apache.lucene.analysis.MockPayloadAnalyzer;
|
||||
import org.apache.lucene.analysis.MockTokenizer;
|
||||
import org.apache.lucene.analysis.TokenStream;
|
||||
import org.apache.lucene.analysis.MockAnalyzer;
|
||||
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
|
||||
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
|
||||
import org.apache.lucene.analysis.tokenattributes.PayloadAttribute;
|
||||
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.document.Field;
|
||||
|
@ -41,8 +39,6 @@ import org.apache.lucene.index.SlowMultiReaderWrapper;
|
|||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.queryParser.QueryParser;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.analysis.TokenFilter;
|
||||
import org.apache.lucene.index.Payload;
|
||||
import org.apache.lucene.search.payloads.PayloadSpanUtil;
|
||||
import org.apache.lucene.search.spans.SpanNearQuery;
|
||||
import org.apache.lucene.search.spans.SpanQuery;
|
||||
|
@ -200,7 +196,7 @@ public class TestPositionIncrement extends LuceneTestCase {
|
|||
|
||||
// should not find "1 2" because there is a gap of 1 in the index
|
||||
QueryParser qp = new QueryParser(TEST_VERSION_CURRENT, "field",
|
||||
new MockAnalyzer(MockTokenizer.WHITESPACE, false, stopStopList, false));
|
||||
new MockAnalyzer(MockTokenizer.WHITESPACE, false, stopStopList, false, false));
|
||||
q = (PhraseQuery) qp.parse("\"1 2\"");
|
||||
hits = searcher.search(q, null, 1000).scoreDocs;
|
||||
assertEquals(0, hits.length);
|
||||
|
@ -224,7 +220,7 @@ public class TestPositionIncrement extends LuceneTestCase {
|
|||
|
||||
// when both qp qnd stopFilter propagate increments, we should find the doc.
|
||||
qp = new QueryParser(TEST_VERSION_CURRENT, "field",
|
||||
new MockAnalyzer(MockTokenizer.WHITESPACE, false, stopStopList, true));
|
||||
new MockAnalyzer(MockTokenizer.WHITESPACE, false, stopStopList, true, false));
|
||||
qp.setEnablePositionIncrements(true);
|
||||
q = (PhraseQuery) qp.parse("\"1 stop 2\"");
|
||||
hits = searcher.search(q, null, 1000).scoreDocs;
|
||||
|
@ -241,7 +237,7 @@ public class TestPositionIncrement extends LuceneTestCase {
|
|||
|
||||
public void testPayloadsPos0() throws Exception {
|
||||
Directory dir = newDirectory();
|
||||
RandomIndexWriter writer = new RandomIndexWriter(random, dir, new TestPayloadAnalyzer());
|
||||
RandomIndexWriter writer = new RandomIndexWriter(random, dir, new MockPayloadAnalyzer());
|
||||
Document doc = new Document();
|
||||
doc.add(new Field("content", new StringReader(
|
||||
"a a b c d e a f g h i j a b k k")));
|
||||
|
@ -327,57 +323,4 @@ public class TestPositionIncrement extends LuceneTestCase {
|
|||
is.getIndexReader().close();
|
||||
dir.close();
|
||||
}
|
||||
}
|
||||
|
||||
final class TestPayloadAnalyzer extends Analyzer {
|
||||
|
||||
@Override
|
||||
public TokenStream tokenStream(String fieldName, Reader reader) {
|
||||
TokenStream result = new MockTokenizer(reader, MockTokenizer.WHITESPACE, true);
|
||||
return new PayloadFilter(result, fieldName);
|
||||
}
|
||||
}
|
||||
|
||||
final class PayloadFilter extends TokenFilter {
|
||||
String fieldName;
|
||||
|
||||
int pos;
|
||||
|
||||
int i;
|
||||
|
||||
final PositionIncrementAttribute posIncrAttr;
|
||||
final PayloadAttribute payloadAttr;
|
||||
final CharTermAttribute termAttr;
|
||||
|
||||
public PayloadFilter(TokenStream input, String fieldName) {
|
||||
super(input);
|
||||
this.fieldName = fieldName;
|
||||
pos = 0;
|
||||
i = 0;
|
||||
posIncrAttr = input.addAttribute(PositionIncrementAttribute.class);
|
||||
payloadAttr = input.addAttribute(PayloadAttribute.class);
|
||||
termAttr = input.addAttribute(CharTermAttribute.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean incrementToken() throws IOException {
|
||||
if (input.incrementToken()) {
|
||||
payloadAttr.setPayload(new Payload(("pos: " + pos).getBytes()));
|
||||
int posIncr;
|
||||
if (i % 2 == 1) {
|
||||
posIncr = 1;
|
||||
} else {
|
||||
posIncr = 0;
|
||||
}
|
||||
posIncrAttr.setPositionIncrement(posIncr);
|
||||
pos += posIncr;
|
||||
if (TestPositionIncrement.VERBOSE) {
|
||||
System.out.println("term=" + termAttr + " pos=" + pos);
|
||||
}
|
||||
i++;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,12 +18,18 @@ package org.apache.lucene.search.spans;
|
|||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.lucene.analysis.MockAnalyzer;
|
||||
import org.apache.lucene.analysis.MockPayloadAnalyzer;
|
||||
import org.apache.lucene.analysis.MockTokenizer;
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.index.Payload;
|
||||
import org.apache.lucene.index.RandomIndexWriter;
|
||||
import org.apache.lucene.index.SlowMultiReaderWrapper;
|
||||
import org.apache.lucene.index.Term;
|
||||
|
@ -65,11 +71,11 @@ public class TestBasics extends LuceneTestCase {
|
|||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
directory = newDirectory();
|
||||
RandomIndexWriter writer = new RandomIndexWriter(random, directory,
|
||||
newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(MockTokenizer.SIMPLE, true))
|
||||
RandomIndexWriter writer = new RandomIndexWriter(random, directory,
|
||||
newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(MockTokenizer.SIMPLE, true, true))
|
||||
.setMaxBufferedDocs(_TestUtil.nextInt(random, 50, 1000)));
|
||||
//writer.infoStream = System.out;
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
Document doc = new Document();
|
||||
doc.add(newField("field", English.intToEnglish(i), Field.Store.YES, Field.Index.ANALYZED));
|
||||
writer.addDocument(doc);
|
||||
|
@ -94,12 +100,23 @@ public class TestBasics extends LuceneTestCase {
|
|||
Query query = new TermQuery(new Term("field", "seventy"));
|
||||
checkHits(query, new int[]
|
||||
{70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 170, 171, 172, 173, 174, 175,
|
||||
176, 177, 178, 179, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279,
|
||||
370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 470, 471, 472, 473,
|
||||
474, 475, 476, 477, 478, 479, 570, 571, 572, 573, 574, 575, 576, 577,
|
||||
578, 579, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 770, 771,
|
||||
772, 773, 774, 775, 776, 777, 778, 779, 870, 871, 872, 873, 874, 875,
|
||||
876, 877, 878, 879, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979});
|
||||
176, 177, 178, 179, 270, 271, 272, 273, 274, 275, 276, 277, 278,
|
||||
279, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 470, 471,
|
||||
472, 473, 474, 475, 476, 477, 478, 479, 570, 571, 572, 573, 574,
|
||||
575, 576, 577, 578, 579, 670, 671, 672, 673, 674, 675, 676, 677,
|
||||
678, 679, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 870,
|
||||
871, 872, 873, 874, 875, 876, 877, 878, 879, 970, 971, 972, 973,
|
||||
974, 975, 976, 977, 978, 979, 1070, 1071, 1072, 1073, 1074, 1075,
|
||||
1076, 1077, 1078, 1079, 1170, 1171, 1172, 1173, 1174, 1175, 1176,
|
||||
1177, 1178, 1179, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277,
|
||||
1278, 1279, 1370, 1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378,
|
||||
1379, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479,
|
||||
1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1670,
|
||||
1671, 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1770, 1771,
|
||||
1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1870, 1871, 1872,
|
||||
1873, 1874, 1875, 1876, 1877,
|
||||
1878, 1879, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978,
|
||||
1979});
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -114,7 +131,8 @@ public class TestBasics extends LuceneTestCase {
|
|||
query.add(new Term("field", "seventy"));
|
||||
query.add(new Term("field", "seven"));
|
||||
checkHits(query, new int[]
|
||||
{77, 177, 277, 377, 477, 577, 677, 777, 877, 977});
|
||||
{77, 177, 277, 377, 477, 577, 677, 777, 877,
|
||||
977, 1077, 1177, 1277, 1377, 1477, 1577, 1677, 1777, 1877, 1977});
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -131,8 +149,10 @@ public class TestBasics extends LuceneTestCase {
|
|||
query.add(new TermQuery(new Term("field", "seventy")), BooleanClause.Occur.MUST);
|
||||
query.add(new TermQuery(new Term("field", "seven")), BooleanClause.Occur.MUST);
|
||||
checkHits(query, new int[]
|
||||
{77, 777, 177, 277, 377, 477, 577, 677, 770, 771, 772, 773, 774, 775,
|
||||
776, 778, 779, 877, 977});
|
||||
{77, 177, 277, 377, 477, 577, 677, 770, 771, 772, 773, 774, 775, 776, 777,
|
||||
778, 779, 877, 977, 1077, 1177, 1277, 1377, 1477, 1577, 1677,
|
||||
1770, 1771, 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1877,
|
||||
1977});
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -150,7 +170,7 @@ public class TestBasics extends LuceneTestCase {
|
|||
SpanNearQuery query = new SpanNearQuery(new SpanQuery[] {term1, term2},
|
||||
0, true);
|
||||
checkHits(query, new int[]
|
||||
{77, 177, 277, 377, 477, 577, 677, 777, 877, 977});
|
||||
{77, 177, 277, 377, 477, 577, 677, 777, 877, 977, 1077, 1177, 1277, 1377, 1477, 1577, 1677, 1777, 1877, 1977});
|
||||
|
||||
assertTrue(searcher.explain(query, 77).getValue() > 0.0f);
|
||||
assertTrue(searcher.explain(query, 977).getValue() > 0.0f);
|
||||
|
@ -168,8 +188,10 @@ public class TestBasics extends LuceneTestCase {
|
|||
4, false);
|
||||
|
||||
checkHits(query, new int[]
|
||||
{609, 629, 639, 649, 659, 669, 679, 689, 699,
|
||||
906, 926, 936, 946, 956, 966, 976, 986, 996});
|
||||
{609, 629, 639, 649, 659, 669, 679, 689, 699, 906, 926, 936, 946, 956,
|
||||
966, 976, 986, 996, 1609, 1629, 1639, 1649, 1659, 1669,
|
||||
1679, 1689, 1699, 1906, 1926, 1936, 1946, 1956, 1966, 1976, 1986,
|
||||
1996});
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -179,7 +201,7 @@ public class TestBasics extends LuceneTestCase {
|
|||
SpanNearQuery query = new SpanNearQuery(new SpanQuery[] {term1, term2},
|
||||
4, true);
|
||||
checkHits(query, new int[]
|
||||
{906, 926, 936, 946, 956, 966, 976, 986, 996});
|
||||
{906, 926, 936, 946, 956, 966, 976, 986, 996, 1906, 1926, 1936, 1946, 1956, 1966, 1976, 1986, 1996});
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -192,7 +214,7 @@ public class TestBasics extends LuceneTestCase {
|
|||
SpanNotQuery query = new SpanNotQuery(near, term3);
|
||||
|
||||
checkHits(query, new int[]
|
||||
{801, 821, 831, 851, 861, 871, 881, 891});
|
||||
{801, 821, 831, 851, 861, 871, 881, 891, 1801, 1821, 1831, 1851, 1861, 1871, 1881, 1891});
|
||||
|
||||
assertTrue(searcher.explain(query, 801).getValue() > 0.0f);
|
||||
assertTrue(searcher.explain(query, 891).getValue() > 0.0f);
|
||||
|
@ -211,7 +233,8 @@ public class TestBasics extends LuceneTestCase {
|
|||
SpanNotQuery query = new SpanNotQuery(near, or);
|
||||
|
||||
checkHits(query, new int[]
|
||||
{801, 821, 831, 851, 861, 871, 881, 891});
|
||||
{801, 821, 831, 851, 861, 871, 881, 891,
|
||||
1801, 1821, 1831, 1851, 1861, 1871, 1881, 1891});
|
||||
|
||||
assertTrue(searcher.explain(query, 801).getValue() > 0.0f);
|
||||
assertTrue(searcher.explain(query, 891).getValue() > 0.0f);
|
||||
|
@ -232,7 +255,7 @@ public class TestBasics extends LuceneTestCase {
|
|||
SpanNotQuery query = new SpanNotQuery(near, or);
|
||||
|
||||
checkHits(query, new int[]
|
||||
{801, 821, 831, 851, 871, 891});
|
||||
{801, 821, 831, 851, 871, 891, 1801, 1821, 1831, 1851, 1871, 1891});
|
||||
|
||||
assertTrue(searcher.explain(query, 801).getValue() > 0.0f);
|
||||
assertTrue(searcher.explain(query, 891).getValue() > 0.0f);
|
||||
|
@ -252,7 +275,8 @@ public class TestBasics extends LuceneTestCase {
|
|||
SpanNotQuery query = new SpanNotQuery(near, exclude);
|
||||
|
||||
checkHits(query, new int[]
|
||||
{801, 821, 831, 851, 861, 871, 881, 891});
|
||||
{801, 821, 831, 851, 861, 871, 881, 891,
|
||||
1801, 1821, 1831, 1851, 1861, 1871, 1881, 1891});
|
||||
|
||||
assertTrue(searcher.explain(query, 801).getValue() > 0.0f);
|
||||
assertTrue(searcher.explain(query, 891).getValue() > 0.0f);
|
||||
|
@ -271,8 +295,13 @@ public class TestBasics extends LuceneTestCase {
|
|||
SpanFirstQuery exclude = new SpanFirstQuery(near, n-1);
|
||||
SpanNotQuery q = new SpanNotQuery(include, exclude);
|
||||
|
||||
checkHits(q, new int[]{40,41,42,43,44,45,46,47,48,49});
|
||||
|
||||
checkHits(q, new int[]{40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048,
|
||||
1049, 1140, 1141, 1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149, 1240, 1241, 1242, 1243, 1244,
|
||||
1245, 1246, 1247, 1248, 1249, 1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, 1348, 1349, 1440, 1441, 1442,
|
||||
1443, 1444, 1445, 1446, 1447, 1448, 1449, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1640,
|
||||
1641, 1642, 1643, 1644, 1645, 1646, 1647,
|
||||
1648, 1649, 1740, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1840, 1841, 1842, 1843, 1844, 1845, 1846,
|
||||
1847, 1848, 1849, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949});
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -295,6 +324,108 @@ public class TestBasics extends LuceneTestCase {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpanPositionRange() throws Exception {
|
||||
SpanPositionRangeQuery query;
|
||||
SpanTermQuery term1 = new SpanTermQuery(new Term("field", "five"));
|
||||
query = new SpanPositionRangeQuery(term1, 1, 2);
|
||||
checkHits(query, new int[]
|
||||
{25,35, 45, 55, 65, 75, 85, 95});
|
||||
assertTrue(searcher.explain(query, 25).getValue() > 0.0f);
|
||||
assertTrue(searcher.explain(query, 95).getValue() > 0.0f);
|
||||
|
||||
query = new SpanPositionRangeQuery(term1, 0, 1);
|
||||
checkHits(query, new int[]
|
||||
{5, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512,
|
||||
513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525,
|
||||
526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538,
|
||||
539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551,
|
||||
552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564,
|
||||
565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577,
|
||||
578, 579, 580, 581, 582, 583, 584,
|
||||
585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597,
|
||||
598, 599});
|
||||
|
||||
query = new SpanPositionRangeQuery(term1, 6, 7);
|
||||
checkHits(query, new int[]{});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpanPayloadCheck() throws Exception {
|
||||
SpanTermQuery term1 = new SpanTermQuery(new Term("field", "five"));
|
||||
Payload pay = new Payload(("pos: " + 5).getBytes());
|
||||
SpanQuery query = new SpanPayloadCheckQuery(term1, Collections.singletonList(pay.getData()));
|
||||
checkHits(query, new int[]
|
||||
{5});
|
||||
assertTrue(searcher.explain(query, 5).getValue() > 0.0f);
|
||||
|
||||
SpanTermQuery term2 = new SpanTermQuery(new Term("field", "hundred"));
|
||||
SpanNearQuery snq;
|
||||
SpanQuery[] clauses;
|
||||
List<byte[]> list;
|
||||
Payload pay2;
|
||||
clauses = new SpanQuery[2];
|
||||
clauses[0] = term1;
|
||||
clauses[1] = term2;
|
||||
snq = new SpanNearQuery(clauses, 0, true);
|
||||
pay = new Payload(("pos: " + 1656).getBytes());
|
||||
pay2 = new Payload(("pos: " + 1657).getBytes());
|
||||
list = new ArrayList<byte[]>();
|
||||
list.add(pay.getData());
|
||||
list.add(pay2.getData());
|
||||
query = new SpanNearPayloadCheckQuery(snq, list);
|
||||
checkHits(query, new int[]
|
||||
{500});
|
||||
clauses = new SpanQuery[3];
|
||||
clauses[0] = term1;
|
||||
clauses[1] = term2;
|
||||
clauses[2] = new SpanTermQuery(new Term("field", "five"));
|
||||
snq = new SpanNearQuery(clauses, 0, true);
|
||||
pay = new Payload(("pos: " + 1670).getBytes());
|
||||
pay2 = new Payload(("pos: " + 1671).getBytes());
|
||||
Payload pay3 = new Payload(("pos: " + 1672).getBytes());
|
||||
list = new ArrayList<byte[]>();
|
||||
list.add(pay.getData());
|
||||
list.add(pay2.getData());
|
||||
list.add(pay3.getData());
|
||||
query = new SpanNearPayloadCheckQuery(snq, list);
|
||||
checkHits(query, new int[]
|
||||
{505});
|
||||
}
|
||||
|
||||
public void testComplexSpanChecks() throws Exception {
|
||||
SpanTermQuery one = new SpanTermQuery(new Term("field", "one"));
|
||||
SpanTermQuery thous = new SpanTermQuery(new Term("field", "thousand"));
|
||||
//should be one position in between
|
||||
SpanTermQuery hundred = new SpanTermQuery(new Term("field", "hundred"));
|
||||
SpanTermQuery three = new SpanTermQuery(new Term("field", "three"));
|
||||
|
||||
SpanNearQuery oneThous = new SpanNearQuery(new SpanQuery[]{one, thous}, 0, true);
|
||||
SpanNearQuery hundredThree = new SpanNearQuery(new SpanQuery[]{hundred, three}, 0, true);
|
||||
SpanNearQuery oneThousHunThree = new SpanNearQuery(new SpanQuery[]{oneThous, hundredThree}, 1, true);
|
||||
SpanQuery query;
|
||||
//this one's too small
|
||||
query = new SpanPositionRangeQuery(oneThousHunThree, 1, 2);
|
||||
checkHits(query, new int[]{});
|
||||
//this one's just right
|
||||
query = new SpanPositionRangeQuery(oneThousHunThree, 0, 6);
|
||||
checkHits(query, new int[]{1103, 1203,1303,1403,1503,1603,1703,1803,1903});
|
||||
|
||||
Collection<byte[]> payloads = new ArrayList<byte[]>();
|
||||
Payload pay = new Payload(("pos: " + 3896).getBytes());
|
||||
Payload pay2 = new Payload(("pos: " + 3897).getBytes());
|
||||
Payload pay3 = new Payload(("pos: " + 3899).getBytes());
|
||||
Payload pay4 = new Payload(("pos: " + 3900).getBytes());
|
||||
payloads.add(pay.getData());
|
||||
payloads.add(pay2.getData());
|
||||
payloads.add(pay3.getData());
|
||||
payloads.add(pay4.getData());
|
||||
query = new SpanNearPayloadCheckQuery(oneThousHunThree, payloads);
|
||||
checkHits(query, new int[]{1103});
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSpanOr() throws Exception {
|
||||
SpanTermQuery term1 = new SpanTermQuery(new Term("field", "thirty"));
|
||||
|
@ -310,7 +441,8 @@ public class TestBasics extends LuceneTestCase {
|
|||
|
||||
checkHits(query, new int[]
|
||||
{33, 47, 133, 147, 233, 247, 333, 347, 433, 447, 533, 547, 633, 647, 733,
|
||||
747, 833, 847, 933, 947});
|
||||
747, 833, 847, 933, 947, 1033, 1047, 1133, 1147, 1233, 1247, 1333,
|
||||
1347, 1433, 1447, 1533, 1547, 1633, 1647, 1733, 1747, 1833, 1847, 1933, 1947});
|
||||
|
||||
assertTrue(searcher.explain(query, 33).getValue() > 0.0f);
|
||||
assertTrue(searcher.explain(query, 947).getValue() > 0.0f);
|
||||
|
@ -330,7 +462,7 @@ public class TestBasics extends LuceneTestCase {
|
|||
SpanNearQuery query = new SpanNearQuery(new SpanQuery[] {near1, near2},
|
||||
0, true);
|
||||
|
||||
checkHits(query, new int[] {333});
|
||||
checkHits(query, new int[] {333, 1333});
|
||||
|
||||
assertTrue(searcher.explain(query, 333).getValue() > 0.0f);
|
||||
}
|
||||
|
@ -351,10 +483,13 @@ public class TestBasics extends LuceneTestCase {
|
|||
10, true);
|
||||
|
||||
checkHits(query, new int[]
|
||||
{606, 607, 626, 627, 636, 637, 646, 647,
|
||||
656, 657, 666, 667, 676, 677, 686, 687, 696, 697,
|
||||
706, 707, 726, 727, 736, 737, 746, 747,
|
||||
756, 757, 766, 767, 776, 777, 786, 787, 796, 797});
|
||||
{606, 607, 626, 627, 636, 637, 646, 647, 656, 657, 666, 667, 676, 677,
|
||||
686, 687, 696, 697, 706, 707, 726, 727, 736, 737, 746, 747, 756,
|
||||
757, 766, 767, 776, 777, 786, 787, 796, 797, 1606, 1607, 1626,
|
||||
1627, 1636, 1637, 1646, 1647, 1656, 1657, 1666, 1667, 1676, 1677,
|
||||
1686, 1687, 1696, 1697, 1706, 1707, 1726, 1727, 1736, 1737,
|
||||
1746, 1747, 1756, 1757, 1766, 1767, 1776, 1777, 1786, 1787, 1796,
|
||||
1797});
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -378,10 +513,12 @@ public class TestBasics extends LuceneTestCase {
|
|||
100, true);
|
||||
|
||||
checkHits(query, new int[]
|
||||
{606, 607, 626, 627, 636, 637, 646, 647,
|
||||
656, 657, 666, 667, 676, 677, 686, 687, 696, 697,
|
||||
706, 707, 726, 727, 736, 737, 746, 747,
|
||||
756, 757, 766, 767, 776, 777, 786, 787, 796, 797});
|
||||
{606, 607, 626, 627, 636, 637, 646, 647, 656, 657, 666, 667, 676, 677, 686, 687, 696,
|
||||
697, 706, 707, 726, 727, 736, 737, 746, 747, 756, 757,
|
||||
766, 767, 776, 777, 786, 787, 796, 797, 1606, 1607, 1626, 1627, 1636, 1637, 1646,
|
||||
1647, 1656, 1657,
|
||||
1666, 1667, 1676, 1677, 1686, 1687, 1696, 1697, 1706, 1707, 1726, 1727, 1736, 1737,
|
||||
1746, 1747, 1756, 1757, 1766, 1767, 1776, 1777, 1786, 1787, 1796, 1797});
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue