Search in sources :

Example 26 with LeafReader

use of org.apache.lucene.index.LeafReader in project lucene-solr by apache.

the class QueryUtils method checkFirstSkipTo.

/** check that first skip on just created scorers always goes to the right doc */
public static void checkFirstSkipTo(final Query q, final IndexSearcher s) throws IOException {
    //System.out.println("checkFirstSkipTo: "+q);
    final float maxDiff = 1e-3f;
    final int[] lastDoc = { -1 };
    final LeafReader[] lastReader = { null };
    final List<LeafReaderContext> context = s.getTopReaderContext().leaves();
    s.search(q, new SimpleCollector() {

        private Scorer scorer;

        private int leafPtr;

        @Override
        public void setScorer(Scorer scorer) {
            this.scorer = scorer;
        }

        @Override
        public void collect(int doc) throws IOException {
            float score = scorer.score();
            try {
                long startMS = System.currentTimeMillis();
                for (int i = lastDoc[0] + 1; i <= doc; i++) {
                    Weight w = s.createNormalizedWeight(q, true);
                    Scorer scorer = w.scorer(context.get(leafPtr));
                    Assert.assertTrue("query collected " + doc + " but advance(" + i + ") says no more docs!", scorer.iterator().advance(i) != DocIdSetIterator.NO_MORE_DOCS);
                    Assert.assertEquals("query collected " + doc + " but advance(" + i + ") got to " + scorer.docID(), doc, scorer.docID());
                    float advanceScore = scorer.score();
                    Assert.assertEquals("unstable advance(" + i + ") score!", advanceScore, scorer.score(), maxDiff);
                    Assert.assertEquals("query assigned doc " + doc + " a score of <" + score + "> but advance(" + i + ") has <" + advanceScore + ">!", score, advanceScore, maxDiff);
                    // if you got SimpleText codec this will kick in):
                    if (i < doc && System.currentTimeMillis() - startMS > 5) {
                        i = doc - 1;
                    }
                }
                lastDoc[0] = doc;
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public boolean needsScores() {
            return true;
        }

        @Override
        protected void doSetNextReader(LeafReaderContext context) throws IOException {
            // previous reader, hits NO_MORE_DOCS
            if (lastReader[0] != null) {
                final LeafReader previousReader = lastReader[0];
                IndexSearcher indexSearcher = LuceneTestCase.newSearcher(previousReader, false);
                indexSearcher.setSimilarity(s.getSimilarity(true));
                Weight w = indexSearcher.createNormalizedWeight(q, true);
                Scorer scorer = w.scorer((LeafReaderContext) indexSearcher.getTopReaderContext());
                if (scorer != null) {
                    DocIdSetIterator iterator = scorer.iterator();
                    boolean more = false;
                    final Bits liveDocs = context.reader().getLiveDocs();
                    for (int d = iterator.advance(lastDoc[0] + 1); d != DocIdSetIterator.NO_MORE_DOCS; d = iterator.nextDoc()) {
                        if (liveDocs == null || liveDocs.get(d)) {
                            more = true;
                            break;
                        }
                    }
                    Assert.assertFalse("query's last doc was " + lastDoc[0] + " but advance(" + (lastDoc[0] + 1) + ") got to " + scorer.docID(), more);
                }
                leafPtr++;
            }
            lastReader[0] = context.reader();
            lastDoc[0] = -1;
        }
    });
    if (lastReader[0] != null) {
        // confirm that skipping beyond the last doc, on the
        // previous reader, hits NO_MORE_DOCS
        final LeafReader previousReader = lastReader[0];
        IndexSearcher indexSearcher = LuceneTestCase.newSearcher(previousReader, false);
        indexSearcher.setSimilarity(s.getSimilarity(true));
        Weight w = indexSearcher.createNormalizedWeight(q, true);
        Scorer scorer = w.scorer((LeafReaderContext) indexSearcher.getTopReaderContext());
        if (scorer != null) {
            DocIdSetIterator iterator = scorer.iterator();
            boolean more = false;
            final Bits liveDocs = lastReader[0].getLiveDocs();
            for (int d = iterator.advance(lastDoc[0] + 1); d != DocIdSetIterator.NO_MORE_DOCS; d = iterator.nextDoc()) {
                if (liveDocs == null || liveDocs.get(d)) {
                    more = true;
                    break;
                }
            }
            Assert.assertFalse("query's last doc was " + lastDoc[0] + " but advance(" + (lastDoc[0] + 1) + ") got to " + scorer.docID(), more);
        }
    }
}
Also used : LeafReader(org.apache.lucene.index.LeafReader) IOException(java.io.IOException) LeafReaderContext(org.apache.lucene.index.LeafReaderContext) Bits(org.apache.lucene.util.Bits)

Example 27 with LeafReader

use of org.apache.lucene.index.LeafReader in project lucene-solr by apache.

the class QueryUtils method checkSkipTo.

/** alternate scorer advance(),advance(),next(),next(),advance(),advance(), etc
   * and ensure a hitcollector receives same docs and scores
   */
public static void checkSkipTo(final Query q, final IndexSearcher s) throws IOException {
    //System.out.println("Checking "+q);
    final List<LeafReaderContext> readerContextArray = s.getTopReaderContext().leaves();
    final int skip_op = 0;
    final int next_op = 1;
    final int[][] orders = { { next_op }, { skip_op }, { skip_op, next_op }, { next_op, skip_op }, { skip_op, skip_op, next_op, next_op }, { next_op, next_op, skip_op, skip_op }, { skip_op, skip_op, skip_op, next_op, next_op } };
    for (int k = 0; k < orders.length; k++) {
        final int[] order = orders[k];
        // System.out.print("Order:");for (int i = 0; i < order.length; i++)
        // System.out.print(order[i]==skip_op ? " skip()":" next()");
        // System.out.println();
        final int[] opidx = { 0 };
        final int[] lastDoc = { -1 };
        // FUTURE: ensure scorer.doc()==-1
        final float maxDiff = 1e-5f;
        final LeafReader[] lastReader = { null };
        s.search(q, new SimpleCollector() {

            private Scorer sc;

            private Scorer scorer;

            private DocIdSetIterator iterator;

            private int leafPtr;

            @Override
            public void setScorer(Scorer scorer) {
                this.sc = scorer;
            }

            @Override
            public void collect(int doc) throws IOException {
                float score = sc.score();
                lastDoc[0] = doc;
                try {
                    if (scorer == null) {
                        Weight w = s.createNormalizedWeight(q, true);
                        LeafReaderContext context = readerContextArray.get(leafPtr);
                        scorer = w.scorer(context);
                        iterator = scorer.iterator();
                    }
                    int op = order[(opidx[0]++) % order.length];
                    // System.out.println(op==skip_op ?
                    // "skip("+(sdoc[0]+1)+")":"next()");
                    boolean more = op == skip_op ? iterator.advance(scorer.docID() + 1) != DocIdSetIterator.NO_MORE_DOCS : iterator.nextDoc() != DocIdSetIterator.NO_MORE_DOCS;
                    int scorerDoc = scorer.docID();
                    float scorerScore = scorer.score();
                    float scorerScore2 = scorer.score();
                    float scoreDiff = Math.abs(score - scorerScore);
                    float scorerDiff = Math.abs(scorerScore2 - scorerScore);
                    boolean success = false;
                    try {
                        assertTrue(more);
                        assertEquals("scorerDoc=" + scorerDoc + ",doc=" + doc, scorerDoc, doc);
                        assertTrue("score=" + score + ", scorerScore=" + scorerScore, scoreDiff <= maxDiff);
                        assertTrue("scorerScorer=" + scorerScore + ", scorerScore2=" + scorerScore2, scorerDiff <= maxDiff);
                        success = true;
                    } finally {
                        if (!success) {
                            if (LuceneTestCase.VERBOSE) {
                                StringBuilder sbord = new StringBuilder();
                                for (int i = 0; i < order.length; i++) {
                                    sbord.append(order[i] == skip_op ? " skip()" : " next()");
                                }
                                System.out.println("ERROR matching docs:" + "\n\t" + (doc != scorerDoc ? "--> " : "") + "doc=" + doc + ", scorerDoc=" + scorerDoc + "\n\t" + (!more ? "--> " : "") + "tscorer.more=" + more + "\n\t" + (scoreDiff > maxDiff ? "--> " : "") + "scorerScore=" + scorerScore + " scoreDiff=" + scoreDiff + " maxDiff=" + maxDiff + "\n\t" + (scorerDiff > maxDiff ? "--> " : "") + "scorerScore2=" + scorerScore2 + " scorerDiff=" + scorerDiff + "\n\thitCollector.doc=" + doc + " score=" + score + "\n\t Scorer=" + scorer + "\n\t Query=" + q + "  " + q.getClass().getName() + "\n\t Searcher=" + s + "\n\t Order=" + sbord + "\n\t Op=" + (op == skip_op ? " skip()" : " next()"));
                            }
                        }
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }

            @Override
            public boolean needsScores() {
                return true;
            }

            @Override
            protected void doSetNextReader(LeafReaderContext context) throws IOException {
                // previous reader, hits NO_MORE_DOCS
                if (lastReader[0] != null) {
                    final LeafReader previousReader = lastReader[0];
                    IndexSearcher indexSearcher = LuceneTestCase.newSearcher(previousReader, false);
                    indexSearcher.setSimilarity(s.getSimilarity(true));
                    Weight w = indexSearcher.createNormalizedWeight(q, true);
                    LeafReaderContext ctx = (LeafReaderContext) indexSearcher.getTopReaderContext();
                    Scorer scorer = w.scorer(ctx);
                    if (scorer != null) {
                        DocIdSetIterator iterator = scorer.iterator();
                        boolean more = false;
                        final Bits liveDocs = context.reader().getLiveDocs();
                        for (int d = iterator.advance(lastDoc[0] + 1); d != DocIdSetIterator.NO_MORE_DOCS; d = iterator.nextDoc()) {
                            if (liveDocs == null || liveDocs.get(d)) {
                                more = true;
                                break;
                            }
                        }
                        Assert.assertFalse("query's last doc was " + lastDoc[0] + " but advance(" + (lastDoc[0] + 1) + ") got to " + scorer.docID(), more);
                    }
                    leafPtr++;
                }
                lastReader[0] = context.reader();
                assert readerContextArray.get(leafPtr).reader() == context.reader();
                this.scorer = null;
                lastDoc[0] = -1;
            }
        });
        if (lastReader[0] != null) {
            // confirm that skipping beyond the last doc, on the
            // previous reader, hits NO_MORE_DOCS
            final LeafReader previousReader = lastReader[0];
            IndexSearcher indexSearcher = LuceneTestCase.newSearcher(previousReader, false);
            indexSearcher.setSimilarity(s.getSimilarity(true));
            Weight w = indexSearcher.createNormalizedWeight(q, true);
            LeafReaderContext ctx = previousReader.getContext();
            Scorer scorer = w.scorer(ctx);
            if (scorer != null) {
                DocIdSetIterator iterator = scorer.iterator();
                boolean more = false;
                final Bits liveDocs = lastReader[0].getLiveDocs();
                for (int d = iterator.advance(lastDoc[0] + 1); d != DocIdSetIterator.NO_MORE_DOCS; d = iterator.nextDoc()) {
                    if (liveDocs == null || liveDocs.get(d)) {
                        more = true;
                        break;
                    }
                }
                Assert.assertFalse("query's last doc was " + lastDoc[0] + " but advance(" + (lastDoc[0] + 1) + ") got to " + scorer.docID(), more);
            }
        }
    }
}
Also used : LeafReader(org.apache.lucene.index.LeafReader) IOException(java.io.IOException) LeafReaderContext(org.apache.lucene.index.LeafReaderContext) Bits(org.apache.lucene.util.Bits)

Example 28 with LeafReader

use of org.apache.lucene.index.LeafReader in project lucene-solr by apache.

the class ExportWriter method getSortDoc.

private SortDoc getSortDoc(SolrIndexSearcher searcher, SortField[] sortFields) throws IOException {
    SortValue[] sortValues = new SortValue[sortFields.length];
    IndexSchema schema = searcher.getSchema();
    for (int i = 0; i < sortFields.length; ++i) {
        SortField sf = sortFields[i];
        String field = sf.getField();
        boolean reverse = sf.getReverse();
        SchemaField schemaField = schema.getField(field);
        FieldType ft = schemaField.getType();
        if (!schemaField.hasDocValues()) {
            throw new IOException(field + " must have DocValues to use this feature.");
        }
        if (ft instanceof TrieIntField) {
            if (reverse) {
                sortValues[i] = new IntValue(field, new IntDesc());
            } else {
                sortValues[i] = new IntValue(field, new IntAsc());
            }
        } else if (ft instanceof TrieFloatField) {
            if (reverse) {
                sortValues[i] = new FloatValue(field, new FloatDesc());
            } else {
                sortValues[i] = new FloatValue(field, new FloatAsc());
            }
        } else if (ft instanceof TrieDoubleField) {
            if (reverse) {
                sortValues[i] = new DoubleValue(field, new DoubleDesc());
            } else {
                sortValues[i] = new DoubleValue(field, new DoubleAsc());
            }
        } else if (ft instanceof TrieLongField) {
            if (reverse) {
                sortValues[i] = new LongValue(field, new LongDesc());
            } else {
                sortValues[i] = new LongValue(field, new LongAsc());
            }
        } else if (ft instanceof StrField) {
            LeafReader reader = searcher.getSlowAtomicReader();
            SortedDocValues vals = reader.getSortedDocValues(field);
            if (reverse) {
                sortValues[i] = new StringValue(vals, field, new IntDesc());
            } else {
                sortValues[i] = new StringValue(vals, field, new IntAsc());
            }
        } else if (ft instanceof TrieDateField) {
            if (reverse) {
                sortValues[i] = new LongValue(field, new LongDesc());
            } else {
                sortValues[i] = new LongValue(field, new LongAsc());
            }
        } else if (ft instanceof BoolField) {
            // This is a bit of a hack, but since the boolean field stores ByteRefs, just like Strings
            // _and_ since "F" happens to sort before "T" (thus false sorts "less" than true)
            // we can just use the existing StringValue here.
            LeafReader reader = searcher.getSlowAtomicReader();
            SortedDocValues vals = reader.getSortedDocValues(field);
            if (reverse) {
                sortValues[i] = new StringValue(vals, field, new IntDesc());
            } else {
                sortValues[i] = new StringValue(vals, field, new IntAsc());
            }
        } else {
            throw new IOException("Sort fields must be one of the following types: int,float,long,double,string,date,boolean");
        }
    }
    if (sortValues.length == 1) {
        return new SingleValueSortDoc(sortValues[0]);
    } else if (sortValues.length == 2) {
        return new DoubleValueSortDoc(sortValues[0], sortValues[1]);
    } else if (sortValues.length == 3) {
        return new TripleValueSortDoc(sortValues[0], sortValues[1], sortValues[2]);
    } else if (sortValues.length == 4) {
        return new QuadValueSortDoc(sortValues[0], sortValues[1], sortValues[2], sortValues[3]);
    } else {
        throw new IOException("A max of 4 sorts can be specified");
    }
}
Also used : StrField(org.apache.solr.schema.StrField) TrieIntField(org.apache.solr.schema.TrieIntField) SortField(org.apache.lucene.search.SortField) TrieDateField(org.apache.solr.schema.TrieDateField) TrieLongField(org.apache.solr.schema.TrieLongField) TrieFloatField(org.apache.solr.schema.TrieFloatField) TrieDoubleField(org.apache.solr.schema.TrieDoubleField) BoolField(org.apache.solr.schema.BoolField) LeafReader(org.apache.lucene.index.LeafReader) IOException(java.io.IOException) SortedDocValues(org.apache.lucene.index.SortedDocValues) FieldType(org.apache.solr.schema.FieldType) SchemaField(org.apache.solr.schema.SchemaField) IndexSchema(org.apache.solr.schema.IndexSchema)

Example 29 with LeafReader

use of org.apache.lucene.index.LeafReader in project lucene-solr by apache.

the class SimpleFacets method getFacetTermEnumCounts.

/**
   * Returns a list of terms in the specified field along with the 
   * corresponding count of documents in the set that match that constraint.
   * This method uses the FilterCache to get the intersection count between <code>docs</code>
   * and the DocSet for each term in the filter.
   *
   * @see FacetParams#FACET_LIMIT
   * @see FacetParams#FACET_ZEROS
   * @see FacetParams#FACET_MISSING
   */
public NamedList<Integer> getFacetTermEnumCounts(SolrIndexSearcher searcher, DocSet docs, String field, int offset, int limit, int mincount, boolean missing, String sort, String prefix, Predicate<BytesRef> termFilter, boolean intersectsCheck) throws IOException {
    /* :TODO: potential optimization...
    * cache the Terms with the highest docFreq and try them first
    * don't enum if we get our max from them
    */
    // Minimum term docFreq in order to use the filterCache for that term.
    int minDfFilterCache = global.getFieldInt(field, FacetParams.FACET_ENUM_CACHE_MINDF, 0);
    // make sure we have a set that is fast for random access, if we will use it for that
    DocSet fastForRandomSet = docs;
    if (minDfFilterCache > 0 && docs instanceof SortedIntDocSet) {
        SortedIntDocSet sset = (SortedIntDocSet) docs;
        fastForRandomSet = new HashDocSet(sset.getDocs(), 0, sset.size());
    }
    IndexSchema schema = searcher.getSchema();
    FieldType ft = schema.getFieldType(field);
    assert !ft.isPointField() : "Point Fields don't support enum method";
    LeafReader r = searcher.getSlowAtomicReader();
    boolean sortByCount = sort.equals("count") || sort.equals("true");
    final int maxsize = limit >= 0 ? offset + limit : Integer.MAX_VALUE - 1;
    final BoundedTreeSet<CountPair<BytesRef, Integer>> queue = sortByCount ? new BoundedTreeSet<CountPair<BytesRef, Integer>>(maxsize) : null;
    final NamedList<Integer> res = new NamedList<>();
    // the smallest value in the top 'N' values    
    int min = mincount - 1;
    int off = offset;
    int lim = limit >= 0 ? limit : Integer.MAX_VALUE;
    BytesRef prefixTermBytes = null;
    if (prefix != null) {
        String indexedPrefix = ft.toInternal(prefix);
        prefixTermBytes = new BytesRef(indexedPrefix);
    }
    Fields fields = r.fields();
    Terms terms = fields == null ? null : fields.terms(field);
    TermsEnum termsEnum = null;
    SolrIndexSearcher.DocsEnumState deState = null;
    BytesRef term = null;
    if (terms != null) {
        termsEnum = terms.iterator();
        if (prefixTermBytes != null) {
            if (termsEnum.seekCeil(prefixTermBytes) == TermsEnum.SeekStatus.END) {
                termsEnum = null;
            } else {
                term = termsEnum.term();
            }
        } else {
            // position termsEnum on first term
            term = termsEnum.next();
        }
    }
    PostingsEnum postingsEnum = null;
    CharsRefBuilder charsRef = new CharsRefBuilder();
    if (docs.size() >= mincount) {
        while (term != null) {
            if (prefixTermBytes != null && !StringHelper.startsWith(term, prefixTermBytes))
                break;
            if (termFilter == null || termFilter.test(term)) {
                int df = termsEnum.docFreq();
                // make a large difference (for example, many terms with df=1).
                if (df > 0 && df > min) {
                    int c;
                    if (df >= minDfFilterCache) {
                        if (deState == null) {
                            deState = new SolrIndexSearcher.DocsEnumState();
                            deState.fieldName = field;
                            deState.liveDocs = r.getLiveDocs();
                            deState.termsEnum = termsEnum;
                            deState.postingsEnum = postingsEnum;
                        }
                        if (intersectsCheck) {
                            c = searcher.intersects(docs, deState) ? 1 : 0;
                        } else {
                            c = searcher.numDocs(docs, deState);
                        }
                        postingsEnum = deState.postingsEnum;
                    } else {
                        // iterate over TermDocs to calculate the intersection
                        // TODO: specialize when base docset is a bitset or hash set (skipDocs)?  or does it matter for this?
                        // TODO: do this per-segment for better efficiency (MultiDocsEnum just uses base class impl)
                        // TODO: would passing deleted docs lead to better efficiency over checking the fastForRandomSet?
                        postingsEnum = termsEnum.postings(postingsEnum, PostingsEnum.NONE);
                        c = 0;
                        if (postingsEnum instanceof MultiPostingsEnum) {
                            MultiPostingsEnum.EnumWithSlice[] subs = ((MultiPostingsEnum) postingsEnum).getSubs();
                            int numSubs = ((MultiPostingsEnum) postingsEnum).getNumSubs();
                            SEGMENTS_LOOP: for (int subindex = 0; subindex < numSubs; subindex++) {
                                MultiPostingsEnum.EnumWithSlice sub = subs[subindex];
                                if (sub.postingsEnum == null)
                                    continue;
                                int base = sub.slice.start;
                                int docid;
                                while ((docid = sub.postingsEnum.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
                                    if (fastForRandomSet.exists(docid + base)) {
                                        c++;
                                        if (intersectsCheck) {
                                            assert c == 1;
                                            break SEGMENTS_LOOP;
                                        }
                                    }
                                }
                            }
                        } else {
                            int docid;
                            while ((docid = postingsEnum.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
                                if (fastForRandomSet.exists(docid)) {
                                    c++;
                                    if (intersectsCheck) {
                                        assert c == 1;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    if (sortByCount) {
                        if (c > min) {
                            BytesRef termCopy = BytesRef.deepCopyOf(term);
                            queue.add(new CountPair<>(termCopy, c));
                            if (queue.size() >= maxsize)
                                min = queue.last().val;
                        }
                    } else {
                        if (c >= mincount && --off < 0) {
                            if (--lim < 0)
                                break;
                            ft.indexedToReadable(term, charsRef);
                            res.add(charsRef.toString(), c);
                        }
                    }
                }
            }
            term = termsEnum.next();
        }
    }
    if (sortByCount) {
        for (CountPair<BytesRef, Integer> p : queue) {
            if (--off >= 0)
                continue;
            if (--lim < 0)
                break;
            ft.indexedToReadable(p.key, charsRef);
            res.add(charsRef.toString(), p.val);
        }
    }
    if (missing) {
        res.add(null, getFieldMissingCount(searcher, docs, field));
    }
    return res;
}
Also used : SortedIntDocSet(org.apache.solr.search.SortedIntDocSet) HashDocSet(org.apache.solr.search.HashDocSet) TermsEnum(org.apache.lucene.index.TermsEnum) CharsRefBuilder(org.apache.lucene.util.CharsRefBuilder) MultiPostingsEnum(org.apache.lucene.index.MultiPostingsEnum) PostingsEnum(org.apache.lucene.index.PostingsEnum) BytesRef(org.apache.lucene.util.BytesRef) LeafReader(org.apache.lucene.index.LeafReader) NamedList(org.apache.solr.common.util.NamedList) Terms(org.apache.lucene.index.Terms) SolrIndexSearcher(org.apache.solr.search.SolrIndexSearcher) FieldType(org.apache.solr.schema.FieldType) Fields(org.apache.lucene.index.Fields) MultiPostingsEnum(org.apache.lucene.index.MultiPostingsEnum) IndexSchema(org.apache.solr.schema.IndexSchema) HashDocSet(org.apache.solr.search.HashDocSet) DocSet(org.apache.solr.search.DocSet) SortedIntDocSet(org.apache.solr.search.SortedIntDocSet) BitDocSet(org.apache.solr.search.BitDocSet)

Example 30 with LeafReader

use of org.apache.lucene.index.LeafReader in project lucene-solr by apache.

the class SolrDocumentFetcher method decorateDocValueFields.

/**
   * This will fetch and add the docValues fields to a given SolrDocument/SolrInputDocument
   *
   * @param doc
   *          A SolrDocument or SolrInputDocument instance where docValues will be added
   * @param docid
   *          The lucene docid of the document to be populated
   * @param fields
   *          The list of docValues fields to be decorated
   */
public void decorateDocValueFields(@SuppressWarnings("rawtypes") SolrDocumentBase doc, int docid, Set<String> fields) throws IOException {
    final List<LeafReaderContext> leafContexts = searcher.getLeafContexts();
    final int subIndex = ReaderUtil.subIndex(docid, leafContexts);
    final int localId = docid - leafContexts.get(subIndex).docBase;
    final LeafReader leafReader = leafContexts.get(subIndex).reader();
    for (String fieldName : fields) {
        final SchemaField schemaField = searcher.getSchema().getFieldOrNull(fieldName);
        if (schemaField == null || !schemaField.hasDocValues() || doc.containsKey(fieldName)) {
            log.warn("Couldn't decorate docValues for field: [{}], schemaField: [{}]", fieldName, schemaField);
            continue;
        }
        FieldInfo fi = searcher.getFieldInfos().fieldInfo(fieldName);
        if (fi == null) {
            // Searcher doesn't have info about this field, hence ignore it.
            continue;
        }
        final DocValuesType dvType = fi.getDocValuesType();
        switch(dvType) {
            case NUMERIC:
                final NumericDocValues ndv = leafReader.getNumericDocValues(fieldName);
                if (ndv == null) {
                    continue;
                }
                Long val;
                if (ndv.advanceExact(localId)) {
                    val = ndv.longValue();
                } else {
                    continue;
                }
                Object newVal = val;
                if (schemaField.getType().isPointField()) {
                    // TODO: Maybe merge PointField with TrieFields here
                    NumberType type = schemaField.getType().getNumberType();
                    switch(type) {
                        case INTEGER:
                            newVal = val.intValue();
                            break;
                        case LONG:
                            newVal = val.longValue();
                            break;
                        case FLOAT:
                            newVal = Float.intBitsToFloat(val.intValue());
                            break;
                        case DOUBLE:
                            newVal = Double.longBitsToDouble(val);
                            break;
                        case DATE:
                            newVal = new Date(val);
                            break;
                        default:
                            throw new AssertionError("Unexpected PointType: " + type);
                    }
                } else {
                    if (schemaField.getType() instanceof TrieIntField) {
                        newVal = val.intValue();
                    } else if (schemaField.getType() instanceof TrieFloatField) {
                        newVal = Float.intBitsToFloat(val.intValue());
                    } else if (schemaField.getType() instanceof TrieDoubleField) {
                        newVal = Double.longBitsToDouble(val);
                    } else if (schemaField.getType() instanceof TrieDateField) {
                        newVal = new Date(val);
                    } else if (schemaField.getType() instanceof EnumField) {
                        newVal = ((EnumField) schemaField.getType()).intValueToStringValue(val.intValue());
                    }
                }
                doc.addField(fieldName, newVal);
                break;
            case BINARY:
                BinaryDocValues bdv = leafReader.getBinaryDocValues(fieldName);
                if (bdv == null) {
                    continue;
                }
                BytesRef value;
                if (bdv.advanceExact(localId)) {
                    value = BytesRef.deepCopyOf(bdv.binaryValue());
                } else {
                    continue;
                }
                doc.addField(fieldName, value);
                break;
            case SORTED:
                SortedDocValues sdv = leafReader.getSortedDocValues(fieldName);
                if (sdv == null) {
                    continue;
                }
                if (sdv.advanceExact(localId)) {
                    final BytesRef bRef = sdv.binaryValue();
                    // Special handling for Boolean fields since they're stored as 'T' and 'F'.
                    if (schemaField.getType() instanceof BoolField) {
                        doc.addField(fieldName, schemaField.getType().toObject(schemaField, bRef));
                    } else {
                        doc.addField(fieldName, bRef.utf8ToString());
                    }
                }
                break;
            case SORTED_NUMERIC:
                final SortedNumericDocValues numericDv = leafReader.getSortedNumericDocValues(fieldName);
                NumberType type = schemaField.getType().getNumberType();
                if (numericDv != null) {
                    if (numericDv.advance(localId) == localId) {
                        final List<Object> outValues = new ArrayList<Object>(numericDv.docValueCount());
                        for (int i = 0; i < numericDv.docValueCount(); i++) {
                            long number = numericDv.nextValue();
                            switch(type) {
                                case INTEGER:
                                    outValues.add((int) number);
                                    break;
                                case LONG:
                                    outValues.add(number);
                                    break;
                                case FLOAT:
                                    outValues.add(NumericUtils.sortableIntToFloat((int) number));
                                    break;
                                case DOUBLE:
                                    outValues.add(NumericUtils.sortableLongToDouble(number));
                                    break;
                                case DATE:
                                    outValues.add(new Date(number));
                                    break;
                                default:
                                    throw new AssertionError("Unexpected PointType: " + type);
                            }
                        }
                        assert outValues.size() > 0;
                        doc.addField(fieldName, outValues);
                    }
                }
            case SORTED_SET:
                final SortedSetDocValues values = leafReader.getSortedSetDocValues(fieldName);
                if (values != null && values.getValueCount() > 0) {
                    if (values.advance(localId) == localId) {
                        final List<Object> outValues = new LinkedList<>();
                        for (long ord = values.nextOrd(); ord != SortedSetDocValues.NO_MORE_ORDS; ord = values.nextOrd()) {
                            value = values.lookupOrd(ord);
                            outValues.add(schemaField.getType().toObject(schemaField, value));
                        }
                        assert outValues.size() > 0;
                        doc.addField(fieldName, outValues);
                    }
                }
            case NONE:
                break;
        }
    }
}
Also used : NumericDocValues(org.apache.lucene.index.NumericDocValues) SortedNumericDocValues(org.apache.lucene.index.SortedNumericDocValues) SortedNumericDocValues(org.apache.lucene.index.SortedNumericDocValues) TrieIntField(org.apache.solr.schema.TrieIntField) ArrayList(java.util.ArrayList) TrieDateField(org.apache.solr.schema.TrieDateField) BinaryDocValues(org.apache.lucene.index.BinaryDocValues) LeafReaderContext(org.apache.lucene.index.LeafReaderContext) DocValuesType(org.apache.lucene.index.DocValuesType) TrieFloatField(org.apache.solr.schema.TrieFloatField) BytesRef(org.apache.lucene.util.BytesRef) TrieDoubleField(org.apache.solr.schema.TrieDoubleField) EnumField(org.apache.solr.schema.EnumField) BoolField(org.apache.solr.schema.BoolField) LeafReader(org.apache.lucene.index.LeafReader) Date(java.util.Date) SortedDocValues(org.apache.lucene.index.SortedDocValues) LinkedList(java.util.LinkedList) SchemaField(org.apache.solr.schema.SchemaField) NumberType(org.apache.solr.schema.NumberType) SortedSetDocValues(org.apache.lucene.index.SortedSetDocValues) FieldInfo(org.apache.lucene.index.FieldInfo)

Aggregations

LeafReader (org.apache.lucene.index.LeafReader)187 BytesRef (org.apache.lucene.util.BytesRef)69 LeafReaderContext (org.apache.lucene.index.LeafReaderContext)68 Document (org.apache.lucene.document.Document)65 Directory (org.apache.lucene.store.Directory)62 MockAnalyzer (org.apache.lucene.analysis.MockAnalyzer)55 DirectoryReader (org.apache.lucene.index.DirectoryReader)49 RandomIndexWriter (org.apache.lucene.index.RandomIndexWriter)42 Test (org.junit.Test)41 IndexWriter (org.apache.lucene.index.IndexWriter)35 Terms (org.apache.lucene.index.Terms)34 NumericDocValues (org.apache.lucene.index.NumericDocValues)33 TermsEnum (org.apache.lucene.index.TermsEnum)32 IndexReader (org.apache.lucene.index.IndexReader)26 IndexWriterConfig (org.apache.lucene.index.IndexWriterConfig)24 SortedSetDocValues (org.apache.lucene.index.SortedSetDocValues)24 Term (org.apache.lucene.index.Term)24 SortedDocValues (org.apache.lucene.index.SortedDocValues)22 Bits (org.apache.lucene.util.Bits)21 IOException (java.io.IOException)20