net.sf.lucis.core.LucisQuery.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.lucis.core.LucisQuery.java

Source

/*
 * Copyright (C) the original author or authors.
 *
 * Licensed 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.
 */
package net.sf.lucis.core;

import java.util.List;
import java.util.concurrent.TimeUnit;

import net.sf.derquinse.lucis.Group;
import net.sf.derquinse.lucis.GroupResult;
import net.sf.derquinse.lucis.Item;
import net.sf.derquinse.lucis.Page;
import net.sf.derquinse.lucis.Result;
import net.sf.lucis.core.Highlight.HighlightedQuery;
import net.sf.lucis.core.support.AllCollector;
import net.sf.lucis.core.support.CountingCollector;

import org.apache.lucene.document.Document;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.util.OpenBitSet;

import com.google.common.base.MoreObjects;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;

/**
 * Abstract implementation for a search service.
 * @author Andres Rodriguez
 */
public abstract class LucisQuery<T> {
    private LucisQuery() {
    }

    TopDocs getTopDocs(LucisSearcher searcher, Query query, Filter filter, Sort sort, int hits) {
        final TopDocs docs;
        if (sort == null) {
            docs = searcher.search(query, filter, hits);
        } else {
            docs = searcher.search(query, filter, hits, sort);
        }
        return docs;
    }

    public abstract T perform(LucisSearcher searcher);

    public static <T> LucisQuery<Item<T>> first(final Query query, final Filter filter, final Sort sort,
            final DocMapper<T> mapper, final Highlight highlight) {
        return new LucisQuery<Item<T>>() {
            public Item<T> perform(final LucisSearcher searcher) {
                Stopwatch w = Stopwatch.createStarted();
                Query rewritten = searcher.rewrite(query);
                TopDocs docs = getTopDocs(searcher, query, filter, sort, 1);
                if (docs.totalHits > 0) {
                    ScoreDoc sd = docs.scoreDocs[0];
                    Document doc = searcher.doc(sd.doc);
                    HighlightedQuery highlighted = MoreObjects.firstNonNull(highlight, Highlight.no())
                            .highlight(rewritten);
                    float score = sd.score;
                    T item = mapper.map(sd.doc, score, doc, highlighted.getFragments(doc));
                    return new Item<T>(docs.totalHits, score, w.elapsed(TimeUnit.MILLISECONDS), item);
                } else {
                    return new Item<T>(docs.totalHits, 0.0f, w.elapsed(TimeUnit.MILLISECONDS), null);
                }
            }
        };
    }

    public static <T> LucisQuery<Item<T>> first(final Query query, final Filter filter, final Sort sort,
            final DocMapper<T> mapper) {
        return first(query, filter, sort, mapper, Highlight.no());
    }

    public static <T> LucisQuery<Item<T>> first(final Query query, final Sort sort, final DocMapper<T> mapper) {
        return first(query, null, sort, mapper, Highlight.no());
    }

    public static <T> LucisQuery<Item<T>> first(final Query query, final Filter filter, final DocMapper<T> mapper) {
        return first(query, filter, null, mapper, Highlight.no());
    }

    public static <T> LucisQuery<Item<T>> first(final Query query, final DocMapper<T> mapper) {
        return first(query, null, null, mapper, Highlight.no());
    }

    public static <T> LucisQuery<Page<T>> page(final Query query, final Filter filter, final Sort sort,
            final DocMapper<T> mapper, final int first, final int pageSize, final Highlight highlight) {
        return new LucisQuery<Page<T>>() {
            public Page<T> perform(LucisSearcher searcher) {
                Stopwatch w = Stopwatch.createStarted();
                int total = first + pageSize;
                Query rewritten = searcher.rewrite(query);
                TopDocs docs = getTopDocs(searcher, rewritten, filter, sort, total);
                if (docs.totalHits > 0) {
                    int n = Math.min(total, docs.scoreDocs.length);
                    float score = docs.getMaxScore();
                    if (n > first) {
                        final List<T> items = Lists.newArrayListWithCapacity(n - first);
                        HighlightedQuery highlighted = MoreObjects.firstNonNull(highlight, Highlight.no())
                                .highlight(rewritten);
                        for (int i = first; i < n; i++) {
                            ScoreDoc sd = docs.scoreDocs[i];
                            Document doc = searcher.doc(sd.doc);
                            T item = mapper.map(sd.doc, score, doc, highlighted.getFragments(doc));
                            items.add(item);
                        }
                        return new Page<T>(docs.totalHits, score, w.elapsed(TimeUnit.MILLISECONDS), first, items);
                    } else {
                        return new Page<T>(docs.totalHits, score, w.elapsed(TimeUnit.MILLISECONDS), first, null);
                    }
                } else {
                    return new Page<T>(docs.totalHits, 0.0f, w.elapsed(TimeUnit.MILLISECONDS), first, null);
                }
            }
        };
    }

    public static <T> LucisQuery<Page<T>> page(final Query query, final Filter filter, final Sort sort,
            final DocMapper<T> mapper, final int first, final int pageSize) {
        return page(query, filter, sort, mapper, first, pageSize, Highlight.no());
    }

    public static <T> LucisQuery<Page<T>> page(final Query query, final Sort sort, final DocMapper<T> mapper,
            final int first, final int pageSize) {
        return page(query, null, sort, mapper, first, pageSize, Highlight.no());
    }

    public static <T> LucisQuery<Page<T>> page(final Query query, final Filter filter, final DocMapper<T> mapper,
            final int first, final int pageSize) {
        return page(query, filter, null, mapper, first, pageSize, Highlight.no());
    }

    public static <T> LucisQuery<Page<T>> page(final Query query, final DocMapper<T> mapper, final int first,
            final int pageSize) {
        return page(query, null, null, mapper, first, pageSize, Highlight.no());
    }

    public static LucisQuery<Result> count(final Query query, final Filter filter) {
        return new LucisQuery<Result>() {
            @Override
            public Result perform(LucisSearcher searcher) {
                final long t0 = System.currentTimeMillis();
                final CountingCollector collector = new CountingCollector();
                searcher.search(query, filter, collector);
                final long t1 = System.currentTimeMillis();
                return new Result(collector.getCount(), collector.getMaxScore(), t1 - t0);
            }
        };
    }

    public static LucisQuery<GroupResult> group(final Query query, final Filter filter, final List<String> fields) {
        return new LucisQuery<GroupResult>() {
            @Override
            public GroupResult perform(LucisSearcher searcher) {
                final long t0 = System.currentTimeMillis();
                final AllCollector collector = new AllCollector();
                searcher.search(query, filter, collector);
                final Group g = new Group();
                final OpenBitSet bits = collector.getBits();
                for (int i = bits.nextSetBit(0); i >= 0; i = bits.nextSetBit(i + 1)) {
                    g.addHit();
                    final Document d = searcher.doc(i);
                    if (fields != null && !fields.isEmpty()) {
                        add(g, d, 0);
                    }
                }
                final long t1 = System.currentTimeMillis();
                return new GroupResult(g, collector.getMaxScore(), t1 - t0);
            }

            private void add(Group g, Document d, int i) {
                if (i < fields.size()) {
                    final String f = fields.get(i);
                    if (f == null) {
                        return;
                    }
                    i++;
                    String[] values = d.getValues(f);
                    for (String value : values) {
                        Group next = g.getGroup(value);
                        next.addHit();
                        add(next, d, i);
                    }
                }
            }
        };
    }
}