[Mulgara-svn] r1511 - trunk/src/jar/resolver-lucene/java/org/mulgara/resolver/lucene
ronald at mulgara.org
ronald at mulgara.org
Tue Feb 17 12:36:20 UTC 2009
Author: ronald
Date: 2009-02-17 04:36:16 -0800 (Tue, 17 Feb 2009)
New Revision: 1511
Modified:
trunk/src/jar/resolver-lucene/java/org/mulgara/resolver/lucene/FullTextStringIndex.java
trunk/src/jar/resolver-lucene/java/org/mulgara/resolver/lucene/FullTextStringIndexTuples.java
trunk/src/jar/resolver-lucene/java/org/mulgara/resolver/lucene/LuceneResolver.java
Log:
Second attempt at allowing lucene-resolver results to be lazy. Split the
FullTextStringIndexTuples into two, and materialize it for all queries
except fully unconstrained $s $p $o queries (so that things like export
can stream the result out). Support for definable-prefixes is now back in,
albeit in a limited fashion (HybridTuples does not support it, hence it's
only supported in the non-materialized scenario).
Also added some optimizations like sorting the hits by document-id order
for faster doc retrieval.
Modified: trunk/src/jar/resolver-lucene/java/org/mulgara/resolver/lucene/FullTextStringIndex.java
===================================================================
--- trunk/src/jar/resolver-lucene/java/org/mulgara/resolver/lucene/FullTextStringIndex.java 2009-02-17 11:45:47 UTC (rev 1510)
+++ trunk/src/jar/resolver-lucene/java/org/mulgara/resolver/lucene/FullTextStringIndex.java 2009-02-17 12:36:16 UTC (rev 1511)
@@ -31,6 +31,8 @@
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
// Log4J
@@ -818,6 +820,14 @@
return hits.get(n).score;
}
+ public void sort() {
+ Collections.sort(hits, new Comparator<ScoreDoc>() {
+ public int compare(ScoreDoc sd1, ScoreDoc sd2) {
+ return (sd1.doc < sd2.doc) ? -1 : (sd1.doc == sd2.doc) ? 0 : +1;
+ }
+ });
+ }
+
public void close() throws IOException {
if (closed) return;
Modified: trunk/src/jar/resolver-lucene/java/org/mulgara/resolver/lucene/FullTextStringIndexTuples.java
===================================================================
--- trunk/src/jar/resolver-lucene/java/org/mulgara/resolver/lucene/FullTextStringIndexTuples.java 2009-02-17 11:45:47 UTC (rev 1510)
+++ trunk/src/jar/resolver-lucene/java/org/mulgara/resolver/lucene/FullTextStringIndexTuples.java 2009-02-17 12:36:16 UTC (rev 1511)
@@ -40,7 +40,7 @@
import org.apache.log4j.Logger;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.FieldSelector;
-import org.apache.lucene.document.FieldSelectorResult;
+import org.apache.lucene.document.MapFieldSelector;
// JRDf
import org.jrdf.graph.BlankNode;
@@ -51,7 +51,6 @@
import org.mulgara.query.Constraint;
import org.mulgara.query.ConstraintElement;
import org.mulgara.query.LocalNode;
-import org.mulgara.query.QueryException;
import org.mulgara.query.TuplesException;
import org.mulgara.query.Variable;
import org.mulgara.query.rdf.LiteralImpl;
@@ -64,65 +63,50 @@
import org.mulgara.store.tuples.Annotation;
import org.mulgara.store.tuples.DefinablePrefixAnnotation;
import org.mulgara.store.tuples.MandatoryBindingAnnotation;
+import org.mulgara.store.tuples.RowComparator;
import org.mulgara.store.tuples.Tuples;
+import org.mulgara.store.tuples.TuplesOperations;
/**
- * A {@link Tuples} backed by a {@link FullTextStringIndex}.
+ * A {@link Tuples} backed by a {@link FullTextStringIndex}. This is split into two parts, an
+ * upper layer which mostly delegates all methods to another tuples, and a lower layer which is
+ * a direct tuples around the lucene search hits. This allows us to conditionally materialize
+ * the results by materializing the lower-layer tuples.
*
+ * <p>The observed performance of lucene is such that running one larger query is faster than
+ * running, say, 100 smaller queries; at the same time, however, retrieving all the documents
+ * for the results usually takes several times longer than the actual query took. We therefore
+ * run a single query for the given constraint (rather than, say, running a query on each
+ * <code>beforeFirst</code> with the currently bound values) which gathers the document id's
+ * and scores. The documents are then retrieved on-demand by the lower-layer tuples; for most
+ * queries we then just materialize that tuples rather than creating our own document-cache
+ * (lucene does not explicitly cache documents) so repeated iterations over the results are
+ * fast.
+ *
* @created 2002-03-27
- *
* @author <a href="http://staff.pisoftware.com/raboczi">Simon Raboczi</a>
- *
- * @version $Revision: 1.10 $
- *
- * @modified $Date: 2005/05/02 20:07:57 $
- *
- * @maintenanceAuthor $Author: raboczi $
- *
* @company <A href="mailto:info at PIsoftware.com">Plugged In Software</A>
- *
* @copyright © 2002-2004 <A href="http://www.PIsoftware.com/">Plugged In
* Software Pty Ltd</A>
- *
* @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
*/
class FullTextStringIndexTuples extends AbstractTuples implements Resolution, Cloneable {
/** Logger. */
private final static Logger logger = Logger.getLogger(FullTextStringIndexTuples.class);
- /** The native Lucene query result to represent as a {@link Tuples}. */
- private FullTextStringIndex.Hits hits;
-
- /** Which fields to load from the documents. */
- private FieldSelector fieldSelector;
-
- /**
- * The current document within the {@link #hits}.
- *
- * A Lucene document hit corresponds to a {@link Tuples} row.
- */
- private Document document;
-
- /** The index of the next {@link #document} within the {@link #hits}. */
- private int nextDocumentIndex = 0;
-
/** Session used to localize Lucene text into string pool nodes. */
private final ResolverSession session;
- /** The number of items in tuples */
- private long rowCount = -1;
-
/** The upper bound on the number of items in tuples */
private long rowUpperBound = -1;
+ /** The real results. */
+ private Tuples results = null;
+
/** The list of variables as found in the constraint */
private final List<Variable> constrVariableList = new ArrayList<Variable>(4);
/** The list of lucene keys corresponding to the variables found in the constraint */
private final List<String> constrLuceneKeyList = new ArrayList<String>(3);
- /** The current list of variables (possibly re-ordered from definePrefix()) */
- private final List<Variable> variableList = new ArrayList<Variable>(4);
- /** The list of lucene keys corresponding to the (re-ordered) variable-list */
- private final List<String> luceneKeyList = new ArrayList<String>(3);
private final FullTextStringIndex fullTextStringIndex;
private final LuceneConstraint constraint;
@@ -146,10 +130,10 @@
* @param fullTextStringIndex PARAMETER TO DO
* @param constraint the single constraint
* @param session a session context for globalization, etc
- * @throws QueryException if the set of triples couldn't be determined
+ * @throws TuplesException if the set of triples couldn't be determined
*/
FullTextStringIndexTuples(FullTextStringIndex fullTextStringIndex,
- LuceneConstraint constraint, ResolverSession session) throws QueryException {
+ LuceneConstraint constraint, ResolverSession session) throws TuplesException {
this.fullTextStringIndex = fullTextStringIndex;
this.session = session;
this.constraint = constraint;
@@ -186,8 +170,25 @@
setVariables(constrVariableList);
- variableList.addAll(constrVariableList);
- luceneKeyList.addAll(constrLuceneKeyList);
+ /* run the query now and materialize the result; it is often much faster to run a large query
+ * and grab all resulting lucene documents than it is to run many smaller queries. Ideally we
+ * would try and figure out which approach is better on a query-by-query basis.
+ *
+ * One special case is the all-variable query, which retrieves the whole db - this one is not
+ * materialized because it's usually only used by export().
+ */
+ String subject = getString(subjectElement);
+ String predicate = getString(predicateElement);
+ String object = getString(objectElement);
+
+ results = new SearchHitsTuples(subject, predicate, object);
+ if (subject != null || predicate != null || object != null) {
+ Tuples old = results;
+ long t0 = System.currentTimeMillis();
+ results = TuplesOperations.materialize(results);
+ logger.debug("materialized " + results.getRowCount() + " lucene results() in " + (System.currentTimeMillis() - t0));
+ old.close();
+ }
}
//
@@ -195,55 +196,31 @@
//
public void beforeFirst(long[] prefix, int suffixTruncation) throws TuplesException {
- final String subject = getString(subjectElement, prefix);
- final String predicate = getString(predicateElement, prefix);
- final String object = getString(objectElement, prefix);
- assert (constraint.getScoreVar() == null || object != null) :
+ assert (constraint.getScoreVar() == null ||
+ getString(objectElement, prefix, constrVariableList) != null) :
"Internal error: lucene-query string not bound even though a score is requested";
- if (logger.isDebugEnabled()) {
- logger.debug("Searching for " + subject + " : " + predicate + " : " + object);
- }
+ results.beforeFirst(prefix, suffixTruncation);
+ }
- try {
- hits = fullTextStringIndex.find(subject, predicate, object);
- } catch (FullTextStringIndexException e) {
- throw new TuplesException("Couldn't generate answer from text index: subject='" + subject +
- "', predicate='" + predicate + "', object='" + object + "'", e);
- }
-
- fieldSelector = new FieldSelector() {
- public FieldSelectorResult accept(String fieldName) {
- if (fieldName.equals(FullTextStringIndex.SUBJECT_KEY) && subject == null ||
- fieldName.equals(FullTextStringIndex.PREDICATE_KEY) && predicate == null ||
- (fieldName.equals(FullTextStringIndex.LITERAL_KEY) ||
- fieldName.equals(FullTextStringIndex.REVERSE_LITERAL_KEY)) && object == null) {
- return FieldSelectorResult.LOAD;
- } else {
- return FieldSelectorResult.NO_LOAD;
- }
- }
- };
-
- document = null;
- nextDocumentIndex = 0;
- rowCount = -1;
- rowUpperBound = -1;
+ private String getString(ConstraintElement ce) throws TuplesException {
+ return getString(ce, NO_PREFIX, constrVariableList);
}
- private String getString(ConstraintElement ce, long[] prefix) throws TuplesException {
+ private String getString(ConstraintElement ce, long[] prefix, List<Variable> vars) throws TuplesException {
long boundVal = 0;
+
if (ce instanceof LocalNode) {
boundVal = ((LocalNode)ce).getValue();
} else if (ce instanceof Variable) {
- int idx = variableList.indexOf(ce);
+ int idx = vars.indexOf(ce);
boundVal = (idx < prefix.length) ? prefix[idx] : 0;
}
if (boundVal == 0) return null;
try {
- Object val = session.globalize(boundVal);
+ Object val = session.globalize(boundVal);
if (val instanceof URIReference) return ((URIReference)val).getURI().toString();
if (val instanceof Literal) return ((Literal)val).getLexicalForm();
if (val instanceof BlankNode) return "";
@@ -255,62 +232,43 @@
}
public void close() throws TuplesException {
- try {
- if (hits != null) hits.close();
- } catch (IOException ioe) {
- throw new TuplesException("Error closing fulltext index hits", ioe);
- }
+ if (results != null)
+ results.close();
}
public FullTextStringIndexTuples clone() {
- FullTextStringIndexTuples clone = (FullTextStringIndexTuples) super.clone();
- if (hits != null) clone.hits = hits.clone();
+ FullTextStringIndexTuples clone = (FullTextStringIndexTuples)super.clone();
+ if (results != null) clone.results = (Tuples)results.clone();
return clone;
}
public long getColumnValue(int column) throws TuplesException {
- try {
- if (column >= 0 && column < luceneKeyList.size()) {
- String luceneKey = luceneKeyList.get(column);
- if (luceneKey == FullTextStringIndex.LITERAL_KEY)
- return session.localize(new LiteralImpl(document.get(luceneKey)));
- else
- return session.localize(new URIReferenceImpl(new URI(document.get(luceneKey))));
- } else if (column == luceneKeyList.size()) {
- // Generate the score column
- return session.localize(new LiteralImpl(hits.score(nextDocumentIndex - 1)));
- } else {
- throw new TuplesException("Column " + column + " does not exist");
- }
- } catch (IOException e) {
- throw new TuplesException("Couldn't get column " + column + " value", e);
- } catch (LocalizeException e) {
- throw new TuplesException("Couldn't localize column " + column + " value", e);
- } catch (URISyntaxException e) {
- throw new TuplesException("Couldn't get column " + column + " value", e);
- }
+ return results.getColumnValue(column);
}
public long getRowCount() throws TuplesException {
- if ((rowCount == -1) && (hits != null)) {
- rowCount = hits.length();
- }
+ if (results == null)
+ beforeFirst();
- return rowCount;
+ return results.getRowCount();
}
public long getRowUpperBound() throws TuplesException {
+ return (results != null) ? results.getRowUpperBound() : getRowUpperBoundEstimate();
+ }
+
+ private long getRowUpperBoundEstimate() throws TuplesException {
if (rowUpperBound == -1) {
try {
- rowUpperBound = (hits != null) ? getRowCount() :
- fullTextStringIndex.getMaxDocs(getString(subjectElement, Tuples.NO_PREFIX),
- getString(predicateElement, Tuples.NO_PREFIX),
- getString(objectElement, Tuples.NO_PREFIX));
+ rowUpperBound = (results != null) ? results.getRowCount() :
+ fullTextStringIndex.getMaxDocs(getString(subjectElement),
+ getString(predicateElement),
+ getString(objectElement));
} catch (FullTextStringIndexException e) {
throw new TuplesException("Couldn't row upper-bound from text index: subject='" +
- getString(subjectElement, Tuples.NO_PREFIX) + "', predicate='" +
- getString(predicateElement, Tuples.NO_PREFIX) + "', object='" +
- getString(objectElement, Tuples.NO_PREFIX) + "'", e);
+ getString(subjectElement) + "', predicate='" +
+ getString(predicateElement) + "', object='" +
+ getString(objectElement) + "'", e);
}
}
@@ -323,17 +281,6 @@
if (bound == 0) return Tuples.ZERO;
if (bound == 1) return Tuples.ONE;
return Tuples.MANY;
-
- /* Exact, but slower
- if (getRowUpperBound() == 0) return Tuples.ZERO;
-
- if (hits == null) beforeFirst();
-
- long count = getRowCount();
- if (count == 0) return Tuples.ZERO;
- if (count == 1) return Tuples.ONE;
- return Tuples.MANY;
- */
}
/**
@@ -346,29 +293,28 @@
}
public boolean hasNoDuplicates() throws TuplesException {
- return false;
+ if (results == null)
+ beforeFirst();
+ return results.hasNoDuplicates();
}
- public List<Tuples> getOperands() {
- return Collections.<Tuples>emptyList();
+ public boolean isMaterialized() {
+ return (results != null) && results.isMaterialized();
}
- public boolean next() throws TuplesException {
- assert hits != null : "next() called without beforeFirst()";
-
- try {
- if (nextDocumentIndex < getRowCount()) {
- document = hits.doc(nextDocumentIndex++, fieldSelector);
- return true;
- } else {
- document = null;
- return false;
- }
- } catch (IOException e) {
- throw new TuplesException("Couldn't obtain next Lucene hit", e);
+ public RowComparator getComparator() {
+ if (results != null) {
+ return results.getComparator();
+ } else {
+ return null;
}
}
+ public boolean next() throws TuplesException {
+ assert results != null : "next() called without beforeFirst()";
+ return results.next();
+ }
+
public Constraint getConstraint() {
return constraint;
}
@@ -378,6 +324,10 @@
return false;
}
+ public List<Tuples> getOperands() {
+ return Collections.singletonList(results);
+ }
+
public Annotation getAnnotation(Class<? extends Annotation> annotationClass) throws TuplesException {
// the object (lucene query string) is required when a score is requested
if (annotationClass == MandatoryBindingAnnotation.class &&
@@ -385,33 +335,196 @@
return new MandatoryBindingAnnotation(new Variable[] { (Variable)objectElement });
}
- // support re-ordering the variables so any variables can be bound in the prefix
- if (annotationClass == DefinablePrefixAnnotation.class) {
- return new DefinablePrefixAnnotation() {
- public void definePrefix(Set boundVars) throws TuplesException {
- if (boundVars.contains(constraint.getScoreVar()))
- throw new TuplesException("Score variable may not be bound");
+ return (results != null) ? results.getAnnotation(annotationClass) : null;
+ }
- variableList.clear();
- luceneKeyList.clear();
+ private class SearchHitsTuples extends AbstractTuples {
+ /** The current list of variables (possibly re-ordered from definePrefix()) */
+ private final List<Variable> variableList = new ArrayList<Variable>(4);
+ /** The list of lucene keys corresponding to the (re-ordered) variable-list */
+ private final List<String> luceneKeyList = new ArrayList<String>(3);
- for (boolean useBound : new boolean[] { true, false }) {
- for (int idx = 0; idx < constrLuceneKeyList.size(); idx++) {
- Variable var = constrVariableList.get(idx);
+ /** The native Lucene query result to represent as a {@link Tuples}. */
+ private FullTextStringIndex.Hits hits;
- if (boundVars.contains(var) == useBound) {
- variableList.add(var);
- luceneKeyList.add(constrLuceneKeyList.get(idx));
+ /** Which fields to load from the documents. */
+ private final FieldSelector fieldSelector;
+
+ /**
+ * The current document within the {@link #hits}.
+ *
+ * A Lucene document hit corresponds to a {@link Tuples} row.
+ */
+ private Document document;
+
+ /** The index of the next {@link #document} within the {@link #hits}. */
+ private int nextDocumentIndex = 0;
+
+ /** the currently bound value for the subject, or null if not bound */
+ private String subject;
+ /** the currently bound value for the predicate, or null if not bound */
+ private String predicate;
+ /** the currently bound value for the object, or null if not bound */
+ private String object;
+
+ public SearchHitsTuples(final String subject, final String predicate, final String object) throws TuplesException {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Searching for " + subject + " : " + predicate + " : " + object);
+ }
+
+ // run the query
+ try {
+ hits = fullTextStringIndex.find(subject, predicate, object);
+ } catch (FullTextStringIndexException e) {
+ throw new TuplesException("Couldn't generate answer from text index: subject='" + subject +
+ "', predicate='" + predicate + "', object='" + object + "'", e);
+ }
+
+ // sort the result in doc-id order for faster document retrieval
+ hits.sort();
+
+ // make sure we only load those fields we need (=> faster document retrieval)
+ List<String> load = new ArrayList<String>(3);
+ if (subject == null) load.add(FullTextStringIndex.SUBJECT_KEY);
+ if (predicate == null) load.add(FullTextStringIndex.PREDICATE_KEY);
+ if (object == null) load.add(FullTextStringIndex.LITERAL_KEY);
+ fieldSelector = new MapFieldSelector(load);
+
+ // prepare for iterating
+ document = null;
+ nextDocumentIndex = 0;
+
+ variableList.addAll(constrVariableList);
+ luceneKeyList.addAll(constrLuceneKeyList);
+
+ setVariables(variableList);
+ }
+
+ public void beforeFirst(long[] prefix, int suffixTruncation) throws TuplesException {
+ subject = getString(subjectElement, prefix, variableList);
+ predicate = getString(predicateElement, prefix, variableList);
+ object = getString(objectElement, prefix, variableList);
+
+ document = null;
+ nextDocumentIndex = 0;
+ }
+
+ public boolean next() throws TuplesException {
+ try {
+ while (nextDocumentIndex < hits.length()) {
+ document = hits.doc(nextDocumentIndex++, fieldSelector);
+ if (matches(subject, document.get(FullTextStringIndex.SUBJECT_KEY)) &&
+ matches(predicate, document.get(FullTextStringIndex.PREDICATE_KEY)) &&
+ matches(object, document.get(FullTextStringIndex.LITERAL_KEY))) {
+ return true;
+ }
+ }
+
+ document = null;
+ return false;
+ } catch (IOException e) {
+ throw new TuplesException("Couldn't obtain next Lucene hit", e);
+ }
+ }
+
+ private boolean matches(String bound, String found) {
+ return bound == null || found == null || bound.equals(found);
+ }
+
+ public long getRowCount() throws TuplesException {
+ return hits.length();
+ }
+
+ public long getRowUpperBound() throws TuplesException {
+ return hits.length();
+ }
+
+ public int getRowCardinality() throws TuplesException {
+ switch (hits.length()) {
+ case 0: return Tuples.ZERO;
+ case 1: return Tuples.ONE;
+ default: return Tuples.MANY;
+ }
+ }
+
+ public List<Tuples> getOperands() {
+ return Collections.<Tuples>emptyList();
+ }
+
+ public long getColumnValue(int column) throws TuplesException {
+ try {
+ if (column >= 0 && column < luceneKeyList.size()) {
+ String luceneKey = luceneKeyList.get(column);
+ if (luceneKey == FullTextStringIndex.LITERAL_KEY)
+ return session.localize(new LiteralImpl(document.get(luceneKey)));
+ else
+ return session.localize(new URIReferenceImpl(new URI(document.get(luceneKey))));
+ } else if (column == luceneKeyList.size()) {
+ // Generate the score column
+ return session.localize(new LiteralImpl(hits.score(nextDocumentIndex - 1)));
+ } else {
+ throw new TuplesException("Column " + column + " does not exist");
+ }
+ } catch (IOException e) {
+ throw new TuplesException("Couldn't get column " + column + " value", e);
+ } catch (LocalizeException e) {
+ throw new TuplesException("Couldn't localize column " + column + " value", e);
+ } catch (URISyntaxException e) {
+ throw new TuplesException("Couldn't get column " + column + " value", e);
+ }
+ }
+
+ public boolean isColumnEverUnbound(int column) throws TuplesException {
+ return false;
+ }
+
+ public boolean hasNoDuplicates() throws TuplesException {
+ return false;
+ }
+
+ public void close() throws TuplesException {
+ try {
+ if (hits != null) hits.close();
+ } catch (IOException ioe) {
+ throw new TuplesException("Error closing fulltext index hits", ioe);
+ }
+ }
+
+ public SearchHitsTuples clone() {
+ SearchHitsTuples clone = (SearchHitsTuples)super.clone();
+ if (hits != null) clone.hits = hits.clone();
+ return clone;
+ }
+
+ public Annotation getAnnotation(Class<? extends Annotation> annotationClass) throws TuplesException {
+ // support re-ordering the variables so any variables can be bound in the prefix
+ if (annotationClass == DefinablePrefixAnnotation.class) {
+ return new DefinablePrefixAnnotation() {
+ public void definePrefix(Set boundVars) throws TuplesException {
+ if (boundVars.contains(constraint.getScoreVar()))
+ throw new TuplesException("Score variable may not be bound");
+
+ variableList.clear();
+ luceneKeyList.clear();
+
+ for (boolean useBound : new boolean[] { true, false }) {
+ for (int idx = 0; idx < constrLuceneKeyList.size(); idx++) {
+ Variable var = constrVariableList.get(idx);
+
+ if (boundVars.contains(var) == useBound) {
+ variableList.add(var);
+ luceneKeyList.add(constrLuceneKeyList.get(idx));
+ }
}
}
+
+ if (constraint.getScoreVar() != null) variableList.add(constraint.getScoreVar());
+ setVariables(variableList);
}
+ };
+ }
- if (constraint.getScoreVar() != null) variableList.add(constraint.getScoreVar());
- setVariables(variableList);
- }
- };
+ return null;
}
-
- return null;
}
}
Modified: trunk/src/jar/resolver-lucene/java/org/mulgara/resolver/lucene/LuceneResolver.java
===================================================================
--- trunk/src/jar/resolver-lucene/java/org/mulgara/resolver/lucene/LuceneResolver.java 2009-02-17 11:45:47 UTC (rev 1510)
+++ trunk/src/jar/resolver-lucene/java/org/mulgara/resolver/lucene/LuceneResolver.java 2009-02-17 12:36:16 UTC (rev 1511)
@@ -71,9 +71,6 @@
import org.mulgara.resolver.spi.ResolverException;
import org.mulgara.resolver.spi.ResolverSession;
import org.mulgara.resolver.spi.Statements;
-import org.mulgara.resolver.spi.TuplesWrapperResolution;
-import org.mulgara.store.tuples.Tuples;
-import org.mulgara.store.tuples.TuplesOperations;
import org.mulgara.util.conversion.html.HtmlToTextConverter;
/**
@@ -372,23 +369,13 @@
// generate the tuples
try {
FullTextStringIndex stringIndex = getFullTextStringIndex(((LocalNode)modelElement).getValue());
-
- /* run the query now and materialize the result; it is often much faster to run a large query
- * and grab all resulting lucene documents than it is to run many smaller queries. Ideally we
- * would try and figure out which approach is better on a query-by-query basis.
- */
- Tuples tmpTuples = new FullTextStringIndexTuples(stringIndex, (LuceneConstraint)constraint, resolverSession);
- Tuples tuples = TuplesOperations.sort(tmpTuples);
- tmpTuples.close();
-
- return new TuplesWrapperResolution(tuples, constraint);
- } catch (TuplesException te) {
- throw new QueryException("Failed to sort tuples and close", te);
-
+ return new FullTextStringIndexTuples(stringIndex, (LuceneConstraint)constraint, resolverSession);
} catch (IOException ioe) {
throw new QueryException("Failed to open string index", ioe);
} catch (FullTextStringIndexException ef) {
throw new QueryException("Query failed against string index", ef);
+ } catch (TuplesException te) {
+ throw new QueryException("Failed to query string index", te);
}
}
More information about the Mulgara-svn
mailing list