Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
net.conquiris.search.AbstractSearcher Maven / Gradle / Ivy
/*
* 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.conquiris.search;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import net.conquiris.api.search.CountResult;
import net.conquiris.api.search.Highlight;
import net.conquiris.api.search.Highlight.HighlightedQuery;
import net.conquiris.api.search.HitMapper;
import net.conquiris.api.search.IndexNotAvailableException;
import net.conquiris.api.search.ItemResult;
import net.conquiris.api.search.PageResult;
import net.conquiris.api.search.SearchException;
import net.conquiris.api.search.Searcher;
import net.conquiris.lucene.search.Hit;
import net.conquiris.lucene.search.ScoredTotalHitCountCollector;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.FieldSelector;
import org.apache.lucene.search.Collector;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.IndexSearcher;
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.search.TopFieldDocs;
import org.apache.lucene.search.TotalHitCountCollector;
import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;
/**
* Abstract searcher implementation.
* @author Andres Rodriguez
*/
abstract class AbstractSearcher implements Searcher {
/** Constructor. */
AbstractSearcher() {
}
/**
* Fetch searcher to use.
* @throws IndexNotAvailableException if an error occurs.
*/
abstract IndexSearcher getIndexSearcher();
/**
* Dispose used searcher.
* @param searcher Searcher to dispose.
*/
abstract void disposeIndexSearcher(IndexSearcher searcher);
/**
* Performs a primitive operation.
* @param operation Operation to perform.
* @return Operation return value.
*/
T perform(Op operation) {
final IndexSearcher searcher = getIndexSearcher();
try {
return operation.apply(searcher);
} finally {
disposeIndexSearcher(searcher);
}
}
/*
* (non-Javadoc)
* @see net.conquiris.api.search.Searcher#doc(int)
*/
public final Document doc(final int i) {
return perform(new Op() {
@Override
Document perform(IndexSearcher searcher) throws Exception {
return searcher.doc(i);
}
});
}
/*
* (non-Javadoc)
* @see net.conquiris.api.search.Searcher#rewrite(org.apache.lucene.search.Query)
*/
public final Query rewrite(final Query query) {
return perform(new Op() {
@Override
Query perform(IndexSearcher searcher) throws Exception {
return searcher.rewrite(query);
}
});
}
/*
* (non-Javadoc)
* @see net.conquiris.api.search.Searcher#search(org.apache.lucene.search.Query,
* org.apache.lucene.search.Filter, org.apache.lucene.search.Collector)
*/
public final void search(final Query query, final Filter filter, final Collector results) {
perform(new Op() {
@Override
Object perform(IndexSearcher searcher) throws Exception {
searcher.search(query, filter, results);
return null;
}
});
}
/*
* (non-Javadoc)
* @see net.conquiris.api.search.Searcher#search(org.apache.lucene.search.Query,
* org.apache.lucene.search.Filter, int)
*/
public final TopDocs search(final Query query, final Filter filter, final int n) {
return perform(new Op() {
@Override
TopDocs perform(IndexSearcher searcher) throws Exception {
return searcher.search(query, filter, n);
}
});
}
public final TopFieldDocs search(final Query query, final Filter filter, final int n, final Sort sort) {
return perform(new Op() {
@Override
TopFieldDocs perform(IndexSearcher searcher) throws Exception {
return searcher.search(query, filter, n, sort);
}
});
}
/** TopDocs helper method. */
private TopDocs getTopDocs(IndexSearcher searcher, Query query, Filter filter, Sort sort, int hits)
throws IOException {
final TopDocs docs;
if (sort == null) {
docs = searcher.search(query, filter, hits);
} else {
docs = searcher.search(query, filter, hits, sort);
}
return docs;
}
/*
* (non-Javadoc)
* @see net.conquiris.api.search.Searcher#getFirst(net.conquiris.api.search.DocMapper,
* org.apache.lucene.search.Query, org.apache.lucene.search.Filter, org.apache.lucene.search.Sort,
* net.conquiris.api.search.Highlight)
*/
public final ItemResult getFirst(final HitMapper mapper, final Query query, final @Nullable Filter filter,
final @Nullable Sort sort, final @Nullable Highlight highlight) {
return perform(new Op>() {
public ItemResult perform(IndexSearcher searcher) throws Exception {
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];
HighlightedQuery highlighted = MoreObjects.firstNonNull(highlight, Highlight.no()).highlight(rewritten);
float score = sd.score;
T item = map(searcher, sd, highlighted, mapper);
return ItemResult.found(docs.totalHits, score, w.elapsed(TimeUnit.MILLISECONDS), item);
} else {
return ItemResult.notFound(w.elapsed(TimeUnit.MILLISECONDS));
}
}
});
}
/*
* (non-Javadoc)
* @see net.conquiris.api.search.Searcher#getPage(net.conquiris.api.search.DocMapper,
* org.apache.lucene.search.Query, int, int, org.apache.lucene.search.Filter,
* org.apache.lucene.search.Sort, net.conquiris.api.search.Highlight)
*/
public final PageResult getPage(final HitMapper mapper, final Query query, final int firstRecord,
final int maxRecords, final @Nullable Filter filter, final @Nullable Sort sort,
final @Nullable Highlight highlight) {
// Corner case
if (maxRecords < 1) {
CountResult r = getCount(query, filter, true);
return PageResult.notFound(r.getTotalHits(), r.getMaxScore(), r.getTime(), firstRecord);
}
// Normal operation
return perform(new Op>() {
public PageResult perform(IndexSearcher searcher) throws Exception {
Stopwatch w = Stopwatch.createStarted();
int total = firstRecord + maxRecords;
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 > firstRecord) {
final List items = Lists.newArrayListWithCapacity(n - firstRecord);
HighlightedQuery highlighted = MoreObjects.firstNonNull(highlight, Highlight.no()).highlight(rewritten);
for (int i = firstRecord; i < n; i++) {
ScoreDoc sd = docs.scoreDocs[i];
T item = map(searcher, sd, highlighted, mapper);
items.add(item);
}
return PageResult.found(docs.totalHits, score, w.elapsed(TimeUnit.MILLISECONDS), firstRecord, items);
} else {
return PageResult.notFound(docs.totalHits, score, w.elapsed(TimeUnit.MILLISECONDS), firstRecord);
}
} else {
return PageResult.notFound(w.elapsed(TimeUnit.MILLISECONDS), firstRecord);
}
}
});
}
/*
* (non-Javadoc)
* @see net.conquiris.api.search.Searcher#getCount(org.apache.lucene.search.Query,
* org.apache.lucene.search.Filter, boolean)
*/
@Override
public CountResult getCount(final Query query, final @Nullable Filter filter, final boolean score) {
return perform(new Op() {
public CountResult perform(IndexSearcher searcher) throws Exception {
final Stopwatch w = Stopwatch.createStarted();
final ScoredTotalHitCountCollector scoredCollector;
final TotalHitCountCollector collector;
if (score) {
scoredCollector = new ScoredTotalHitCountCollector();
collector = scoredCollector;
} else {
scoredCollector = null;
collector = new TotalHitCountCollector();
}
searcher.search(query, filter, collector);
final float maxScore = score ? scoredCollector.getMaxScore() : 1.0f;
return CountResult.of(collector.getTotalHits(), maxScore, w.elapsed(TimeUnit.MILLISECONDS));
}
});
}
/**
* Searcher primitive operation.
* @param Return type.
*/
abstract class Op implements Function {
@Override
public final T apply(IndexSearcher searcher) {
try {
return perform(searcher);
} catch (SearchException e) {
throw e;
} catch (Exception e) {
throw new IndexNotAvailableException(e);
}
}
final H map(IndexSearcher searcher, ScoreDoc sd, HighlightedQuery q, HitMapper mapper) throws Exception {
final int id = sd.doc;
final float score = sd.score;
final Document doc;
FieldSelector selector = mapper.getFieldSelector();
if (selector == null) {
doc = searcher.doc(id);
} else {
doc = searcher.doc(id, selector);
}
final Hit hit = Hit.of(id, score, doc, q.getFragments(doc));
return mapper.apply(hit);
}
abstract T perform(IndexSearcher searcher) throws Exception;
}
}