@Override public Spans getSpans(final LeafReaderContext context, Postings requiredPostings) throws IOException { Terms terms = context.reader().terms(field); if (terms == null) { return null; // field does not exist } ArrayList<Spans> subSpans = new ArrayList<>(clauses.size()); for (SpanWeight w : subWeights) { Spans subSpan = w.getSpans(context, requiredPostings); if (subSpan != null) { subSpans.add(subSpan); } else { return null; // all required } } // all NearSpans require at least two subSpans return (!inOrder) ? new NearSpansUnordered(slop, subSpans) : new NearSpansOrdered(slop, subSpans); }
@Override boolean twoPhaseCurrentDocMatches() throws IOException { assert unpositioned(); oneExhaustedInCurrentDoc = false; while (subSpans[0].nextStartPosition() != NO_MORE_POSITIONS && !oneExhaustedInCurrentDoc) { if (stretchToOrder() && matchWidth <= allowedSlop) { return atFirstInCurrentDoc = true; } } return false; }
/** * Order the subSpans within the same document by using nextStartPosition on all subSpans * after the first as little as necessary. * Return true when the subSpans could be ordered in this way, * otherwise at least one is exhausted in the current doc. */ private boolean stretchToOrder() throws IOException { Spans prevSpans = subSpans[0]; matchStart = prevSpans.startPosition(); assert prevSpans.startPosition() != NO_MORE_POSITIONS : "prevSpans no start position "+prevSpans; assert prevSpans.endPosition() != NO_MORE_POSITIONS; matchWidth = 0; for (int i = 1; i < subSpans.length; i++) { Spans spans = subSpans[i]; assert spans.startPosition() != NO_MORE_POSITIONS; assert spans.endPosition() != NO_MORE_POSITIONS; if (advancePosition(spans, prevSpans.endPosition()) == NO_MORE_POSITIONS) { oneExhaustedInCurrentDoc = true; return false; } matchWidth += (spans.startPosition() - prevSpans.endPosition()); prevSpans = spans; } matchEnd = subSpans[subSpans.length - 1].endPosition(); return true; // all subSpans ordered and non overlapping }
/** Advances the subSpans to just after an ordered match with a minimum slop * that is smaller than the slop allowed by the SpanNearQuery. * @return true iff there is such a match. */ private boolean advanceAfterOrdered() throws IOException { while (more && (inSameDoc || toSameDoc())) { if (stretchToOrder() && shrinkToAfterShortestMatch()) { return true; } } return false; // no more matches }
@Override public int nextStartPosition() throws IOException { if (atFirstInCurrentDoc) { atFirstInCurrentDoc = false; return matchStart; } oneExhaustedInCurrentDoc = false; while (subSpans[0].nextStartPosition() != NO_MORE_POSITIONS && !oneExhaustedInCurrentDoc) { if (stretchToOrder() && matchWidth <= allowedSlop) { return matchStart; } } return matchStart = matchEnd = NO_MORE_POSITIONS; }
/** Order the subSpans within the same document by advancing all later spans * after the previous one. */ private boolean stretchToOrder() throws IOException { matchDoc = subSpans[0].doc(); for (int i = 1; inSameDoc && (i < subSpans.length); i++) { while (! docSpansOrdered(subSpans[i-1], subSpans[i])) { if (! subSpans[i].next()) { inSameDoc = false; more = false; break; } else if (matchDoc != subSpans[i].doc()) { inSameDoc = false; break; } } } return inSameDoc; }
public boolean next() throws IOException { if (firstTime) { firstTime = false; for (int i = 0; i < subSpans.length; i++) { if (! subSpans[i].next()) { more = false; return false; } } more = true; } matchPayload.clear(); return advanceAfterOrdered(); }
/** Advances the subSpans to just after an ordered match with a minimum slop * that is smaller than the slop allowed by the SpanNearQuery. * @return true iff there is such a match. */ private boolean advanceAfterOrdered() throws IOException { while (more && (inSameDoc || toSameDoc())) { if (stretchToOrder() && shrinkToAfterShortestMatch()) { return true; } } return false; // no more matches }
@Override public int nextStartPosition() throws IOException { if (atFirstInCurrentDoc) { atFirstInCurrentDoc = false; return matchStart; } oneExhaustedInCurrentDoc = false; while (subSpans[0].nextStartPosition() != NO_MORE_POSITIONS && !oneExhaustedInCurrentDoc) { if (stretchToOrder() && matchWidth <= allowedSlop) { return matchStart; } } return matchStart = matchEnd = NO_MORE_POSITIONS; }
protected final boolean lessThan(Object o1, Object o2) { SpansCell spans1 = (SpansCell)o1; SpansCell spans2 = (SpansCell)o2; if (spans1.doc() == spans2.doc()) { return NearSpansOrdered.docSpansOrdered(spans1, spans2); } else { return spans1.doc() < spans2.doc(); } } }
public boolean next() throws IOException { if (firstTime) { firstTime = false; for (int i = 0; i < subSpans.length; i++) { if (! subSpans[i].next()) { more = false; return false; } } more = true; } matchPayload.clear(); return advanceAfterOrdered(); }
@Override boolean twoPhaseCurrentDocMatches() throws IOException { assert unpositioned(); oneExhaustedInCurrentDoc = false; while (subSpans[0].nextStartPosition() != NO_MORE_POSITIONS && !oneExhaustedInCurrentDoc) { if (stretchToOrder() && matchWidth <= allowedSlop) { return atFirstInCurrentDoc = true; } } return false; }
public Spans getSpans(final IndexReader reader) throws IOException { if (clauses.size() == 0) // optimize 0-clause case return new SpanOrQuery(getClauses()).getPayloadSpans(reader); if (clauses.size() == 1) // optimize 1-clause case return ((SpanQuery)clauses.get(0)).getPayloadSpans(reader); return inOrder ? (PayloadSpans) new NearSpansOrdered(this, reader) : (PayloadSpans) new NearSpansUnordered(this, reader); }
@Override public int nextStartPosition() throws IOException { if (atFirstInCurrentDoc) { atFirstInCurrentDoc = false; return matchStart; } oneExhaustedInCurrentDoc = false; while (subSpans[0].nextStartPosition() != NO_MORE_POSITIONS && !oneExhaustedInCurrentDoc) { if (stretchToOrder() && matchWidth <= allowedSlop) { return matchStart; } } return matchStart = matchEnd = NO_MORE_POSITIONS; }
/** * Order the subSpans within the same document by using nextStartPosition on all subSpans * after the first as little as necessary. * Return true when the subSpans could be ordered in this way, * otherwise at least one is exhausted in the current doc. */ private boolean stretchToOrder() throws IOException { Spans prevSpans = subSpans[0]; matchStart = prevSpans.startPosition(); assert prevSpans.startPosition() != NO_MORE_POSITIONS : "prevSpans no start position "+prevSpans; assert prevSpans.endPosition() != NO_MORE_POSITIONS; matchWidth = 0; for (int i = 1; i < subSpans.length; i++) { Spans spans = subSpans[i]; assert spans.startPosition() != NO_MORE_POSITIONS; assert spans.endPosition() != NO_MORE_POSITIONS; if (advancePosition(spans, prevSpans.endPosition()) == NO_MORE_POSITIONS) { oneExhaustedInCurrentDoc = true; return false; } matchWidth += (spans.startPosition() - prevSpans.endPosition()); prevSpans = spans; } matchEnd = subSpans[subSpans.length - 1].endPosition(); return true; // all subSpans ordered and non overlapping }
/** Order the subSpans within the same document by advancing all later spans * after the previous one. */ private boolean stretchToOrder() throws IOException { matchDoc = subSpans[0].doc(); for (int i = 1; inSameDoc && (i < subSpans.length); i++) { while (! docSpansOrdered(subSpans[i-1], subSpans[i])) { if (! subSpans[i].next()) { inSameDoc = false; more = false; break; } else if (matchDoc != subSpans[i].doc()) { inSameDoc = false; break; } } } return inSameDoc; }
public boolean skipTo(int target) throws IOException { if (firstTime) { firstTime = false; for (int i = 0; i < subSpans.length; i++) { if (! subSpans[i].skipTo(target)) { more = false; return false; } } more = true; } else if (more && (subSpans[0].doc() < target)) { if (subSpans[0].skipTo(target)) { inSameDoc = false; } else { more = false; return false; } } matchPayload.clear(); return advanceAfterOrdered(); }
@Override boolean twoPhaseCurrentDocMatches() throws IOException { assert unpositioned(); oneExhaustedInCurrentDoc = false; while (subSpans[0].nextStartPosition() != NO_MORE_POSITIONS && !oneExhaustedInCurrentDoc) { if (stretchToOrder() && matchWidth <= allowedSlop) { return atFirstInCurrentDoc = true; } } return false; }