public UnionDocsAndPositionsEnum(IndexReader indexReader, Term[] terms) throws IOException { List<DocsAndPositionsEnum> docsEnums = new LinkedList<DocsAndPositionsEnum>(); final Bits delDocs = indexReader.getDeletedDocs(); for (int i = 0; i < terms.length; i++) { DocsAndPositionsEnum postings = indexReader.termPositionsEnum(delDocs, terms[i].field(), terms[i].bytes()); if (postings != null) { docsEnums.add(postings); } else { if (indexReader.termDocsEnum(delDocs, terms[i].field(), terms[i].bytes()) != null) { // term does exist, but has no positions throw new IllegalStateException( "field \"" + terms[i].field() + "\" was indexed with Field.omitTermFreqAndPositions=true; cannot run PhraseQuery (term=" + terms[i].text() + ")"); } } } _queue = new DocsQueue(docsEnums); _posList = new IntQueue(); }
@Override public Scorer scorer(AtomicReaderContext context, ScorerContext scorerContext) throws IOException { if (termArrays.size() == 0) // optimize zero-term case return null; final IndexReader reader = context.reader; final Bits delDocs = reader.getDeletedDocs(); PhraseQuery.PostingsAndFreq[] postingsFreqs = new PhraseQuery.PostingsAndFreq[termArrays.size()]; for (int pos = 0; pos < postingsFreqs.length; pos++) { Term[] terms = termArrays.get(pos); final DocsAndPositionsEnum postingsEnum; int docFreq; if (terms.length > 1) { postingsEnum = new UnionDocsAndPositionsEnum(reader, terms); // coarse -- this overcounts since a given doc can // have more than one terms: docFreq = 0; for (int termIdx = 0; termIdx < terms.length; termIdx++) { docFreq += reader.docFreq(terms[termIdx]); } } else { final Term term = terms[0]; postingsEnum = reader.termPositionsEnum(delDocs, term.field(), term.bytes()); if (postingsEnum == null) { if (reader.termDocsEnum(delDocs, term.field(), term.bytes()) != null) { // term does exist, but has no positions throw new IllegalStateException( "field \"" + term.field() + "\" was indexed with Field.omitTermFreqAndPositions=true; cannot run PhraseQuery (term=" + term.text() + ")"); } else { // term does not exist return null; } } docFreq = reader.docFreq(term.field(), term.bytes()); } postingsFreqs[pos] = new PhraseQuery.PostingsAndFreq(postingsEnum, docFreq, positions.get(pos).intValue()); } // sort by increasing docFreq order if (slop == 0) { ArrayUtil.quickSort(postingsFreqs); } if (slop == 0) { ExactPhraseScorer s = new ExactPhraseScorer(this, postingsFreqs, similarity, reader.norms(field)); if (s.noDocs) { return null; } else { return s; } } else { return new SloppyPhraseScorer(this, postingsFreqs, similarity, slop, reader.norms(field)); } }