mirror of
https://github.com/querydsl/querydsl.git
synced 2026-07-06 21:05:50 +08:00
215 lines
6.2 KiB
Java
215 lines
6.2 KiB
Java
package com.mysema.query.lucene;
|
|
|
|
import java.io.IOException;
|
|
import java.util.List;
|
|
|
|
import org.apache.commons.collections15.Transformer;
|
|
import org.apache.lucene.document.Document;
|
|
import org.apache.lucene.search.MatchAllDocsQuery;
|
|
import org.apache.lucene.search.Query;
|
|
import org.apache.lucene.search.ScoreDoc;
|
|
import org.apache.lucene.search.Searcher;
|
|
import org.apache.lucene.search.Sort;
|
|
|
|
import com.mysema.commons.lang.CloseableIterator;
|
|
import com.mysema.commons.lang.EmptyCloseableIterator;
|
|
import com.mysema.commons.lang.IteratorAdapter;
|
|
import com.mysema.query.QueryException;
|
|
import com.mysema.query.QueryMetadata;
|
|
import com.mysema.query.QueryModifiers;
|
|
import com.mysema.query.SearchResults;
|
|
import com.mysema.query.SimpleProjectable;
|
|
import com.mysema.query.SimpleQuery;
|
|
import com.mysema.query.support.QueryMixin;
|
|
import com.mysema.query.types.OrderSpecifier;
|
|
import com.mysema.query.types.ParamExpression;
|
|
import com.mysema.query.types.Predicate;
|
|
|
|
public abstract class AbstractLuceneQuery<T,Q extends AbstractLuceneQuery<T,Q>> implements SimpleQuery<Q>,
|
|
SimpleProjectable<T> {
|
|
|
|
private final QueryMixin<Q> queryMixin;
|
|
|
|
private final Searcher searcher;
|
|
|
|
private final LuceneSerializer serializer;
|
|
|
|
private final Transformer<Document, T> transformer;
|
|
|
|
@SuppressWarnings("unchecked")
|
|
public AbstractLuceneQuery(LuceneSerializer serializer, Searcher searcher,
|
|
Transformer<Document, T> transformer) {
|
|
queryMixin = new QueryMixin<Q>((Q) this);
|
|
this.serializer = serializer;
|
|
this.searcher = searcher;
|
|
this.transformer = transformer;
|
|
}
|
|
|
|
public AbstractLuceneQuery(Searcher searcher, Transformer<Document, T> transformer) {
|
|
this(LuceneSerializer.DEFAULT, searcher, transformer);
|
|
}
|
|
|
|
private long innerCount(){
|
|
try {
|
|
final int maxDoc = searcher.maxDoc();
|
|
if (maxDoc == 0) {
|
|
return 0;
|
|
}
|
|
return searcher.search(createQuery(), maxDoc).totalHits;
|
|
} catch (final IOException e) {
|
|
throw new QueryException(e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public long count() {
|
|
return innerCount();
|
|
}
|
|
|
|
@Override
|
|
public long countDistinct() {
|
|
return innerCount();
|
|
}
|
|
|
|
private Query createQuery() {
|
|
if (queryMixin.getMetadata().getWhere() == null) {
|
|
return new MatchAllDocsQuery();
|
|
}
|
|
return serializer.toQuery(queryMixin.getMetadata().getWhere(),
|
|
queryMixin.getMetadata());
|
|
}
|
|
|
|
@Override
|
|
public Q distinct(){
|
|
return queryMixin.distinct();
|
|
}
|
|
|
|
@Override
|
|
public Q limit(long limit) {
|
|
return queryMixin.limit(limit);
|
|
}
|
|
|
|
@Override
|
|
public CloseableIterator<T> iterate() {
|
|
final QueryMetadata metadata = queryMixin.getMetadata();
|
|
final List<OrderSpecifier<?>> orderBys = metadata.getOrderBy();
|
|
final Long queryLimit = metadata.getModifiers().getLimit();
|
|
final Long queryOffset = metadata.getModifiers().getOffset();
|
|
Sort sort = null;
|
|
int limit;
|
|
final int offset = queryOffset != null ? queryOffset.intValue() : 0;
|
|
try {
|
|
limit = searcher.maxDoc();
|
|
} catch (final IOException e) {
|
|
throw new QueryException(e);
|
|
}
|
|
if (queryLimit != null && queryLimit.intValue() < limit) {
|
|
limit = queryLimit.intValue();
|
|
}
|
|
if (!orderBys.isEmpty()) {
|
|
sort = serializer.toSort(orderBys);
|
|
}
|
|
|
|
try {
|
|
ScoreDoc[] scoreDocs;
|
|
if (sort != null) {
|
|
scoreDocs = searcher.search(createQuery(), null,
|
|
limit + offset, sort).scoreDocs;
|
|
} else {
|
|
scoreDocs = searcher.search(createQuery(), limit + offset).scoreDocs;
|
|
}
|
|
if (offset < scoreDocs.length) {
|
|
return new ResultIterator<T>(scoreDocs, offset, searcher, transformer);
|
|
} else {
|
|
return new EmptyCloseableIterator<T>();
|
|
}
|
|
} catch (final IOException e) {
|
|
throw new QueryException(e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public CloseableIterator<T> iterateDistinct() {
|
|
return iterate();
|
|
}
|
|
|
|
private List<T> innerList(){
|
|
return new IteratorAdapter<T>(iterate()).asList();
|
|
}
|
|
|
|
@Override
|
|
public List<T> list() {
|
|
return innerList();
|
|
}
|
|
|
|
@Override
|
|
public List<T> listDistinct() {
|
|
return list();
|
|
}
|
|
|
|
@Override
|
|
public SearchResults<T> listDistinctResults() {
|
|
return listResults();
|
|
}
|
|
|
|
@Override
|
|
public SearchResults<T> listResults() {
|
|
List<T> documents = innerList();
|
|
/*
|
|
* TODO Get rid of count(). It could be implemented by iterating the
|
|
* list results in list* from n to m.
|
|
*/
|
|
return new SearchResults<T>(documents, queryMixin.getMetadata().getModifiers(), innerCount());
|
|
}
|
|
|
|
@Override
|
|
public Q offset(long offset) {
|
|
return queryMixin.offset(offset);
|
|
}
|
|
|
|
@Override
|
|
public Q orderBy(OrderSpecifier<?>... o) {
|
|
return queryMixin.orderBy(o);
|
|
}
|
|
|
|
@Override
|
|
public Q restrict(QueryModifiers modifiers) {
|
|
return queryMixin.restrict(modifiers);
|
|
}
|
|
|
|
@Override
|
|
public <P> Q set(ParamExpression<P> param, P value) {
|
|
return queryMixin.set(param, value);
|
|
}
|
|
|
|
@Override
|
|
public T uniqueResult() {
|
|
try {
|
|
int maxDoc = searcher.maxDoc();
|
|
if (maxDoc == 0) {
|
|
return null;
|
|
}
|
|
final ScoreDoc[] scoreDocs = searcher.search(createQuery(), maxDoc).scoreDocs;
|
|
if (scoreDocs.length > 1) {
|
|
throw new QueryException("More than one result found!");
|
|
} else if (scoreDocs.length == 1) {
|
|
return transformer.transform(searcher.doc(scoreDocs[0].doc));
|
|
} else {
|
|
return null;
|
|
}
|
|
} catch (IOException e) {
|
|
throw new QueryException(e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Q where(final Predicate... e) {
|
|
return queryMixin.where(e);
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return createQuery().toString();
|
|
}
|
|
}
|