luetzkendorf 2004/12/07 09:49:58
Modified: src/stores/org/apache/slide/index/lucene Index.java
IndexConfiguration.java
LuceneExpressionFactory.java
LucenePropertiesIndexer.java
src/stores/org/apache/slide/index/lucene/expressions
AbstractLuceneExpression.java
BetweenExpression.java ContainsExpression.java
GtExpression.java IsCollectionExpression.java
IsDefinedExpression.java LikeExpression.java
LtExpression.java MergeExpression.java
PropcontainsExpression.java
PropertyContainsExpression.java
Added: src/stores/org/apache/slide/index/lucene/expressions
RangeOperator.java
Log:
some improvemens (negation handling, range query optimization, ...)
Revision Changes Path
1.8 +51 -29
jakarta-slide/src/stores/org/apache/slide/index/lucene/Index.java
Index: Index.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/Index.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- Index.java 29 Nov 2004 18:38:46 -0000 1.7
+++ Index.java 7 Dec 2004 17:49:57 -0000 1.8
@@ -47,6 +47,7 @@
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
+import org.apache.slide.common.PropertyName;
import org.apache.slide.common.Uri;
import org.apache.slide.content.NodeProperty;
import org.apache.slide.content.NodeRevisionDescriptor;
@@ -69,6 +70,7 @@
public static final String VERSION_FIELD_NAME = "SLIDE_VERSION";
public static final String IS_DEFINED_FIELD_NAME = "SLIDE_ISDEFINED";
public static final String CONTENT_FIELD_NAME = "SLIDE_CONTENT";
+ public static final String NULL_FIELD_NAME = "SLIDE_NULL";
protected static final SimpleDateFormat DATE_INDEX_FORMAT =
new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.UK);
@@ -241,19 +243,18 @@
// all other properties
for(Enumeration e = descriptor.enumerateProperties();
e.hasMoreElements();) {
NodeProperty property = (NodeProperty)e.nextElement();
- String name = property.getName();
- String namespace = property.getNamespace();
+ PropertyName propertyName = property.getPropertyName();
Object value = property.getValue();
if (value == null) continue;
- if (!configuration.isIndexedProperty(namespace, name)) continue;
+ if (!configuration.isIndexedProperty(propertyName)) continue;
- if (configuration.isStringProperty(namespace, name)) {
+ if (configuration.isStringProperty(propertyName)) {
doc.add(unstoredString(configuration.generateFieldName(
property.getNamespace(), property.getName()),
value.toString()));
}
- if (configuration.isDateProperty(namespace, name)) {
+ if (configuration.isDateProperty(propertyName)) {
Date date = IndexConfiguration.getDateValue(value);
if (date != null) {
doc.add(unstoredString(configuration.generateFieldName(
@@ -261,7 +262,7 @@
configuration.dateToIndexString(date)));
}
}
- if (configuration.isIntProperty(namespace, name)) {
+ if (configuration.isIntProperty(propertyName)) {
try {
doc.add(unstoredString(configuration.generateFieldName(
property.getNamespace(), property.getName()),
@@ -271,12 +272,12 @@
// TODO log warning
}
}
- if (configuration.isTextProperty(namespace, name)) {
+ if (configuration.isTextProperty(propertyName)) {
doc.add(textField(configuration.generateFieldName(
property.getNamespace(), property.getName()),
value.toString()));
}
- if (configuration.supportsIsDefined(namespace, name)) {
+ if (configuration.supportsIsDefined(propertyName)) {
doc.add(unstoredString(Index.IS_DEFINED_FIELD_NAME,
configuration.generateFieldName(
property.getNamespace(),
property.getName())));
@@ -291,7 +292,7 @@
*/
private Document createLuceneDocument(String uri,
NodeRevisionDescriptor descriptor, InputStream content)
- throws IndexException
+ throws IndexException, ExtractorException
{
Document doc = new Document();
@@ -316,15 +317,11 @@
List extractors =
ExtractorManager.getInstance().getContentExtractors(
configuration.getNamespaceName(), uri, descriptor);
- try {
- for(Iterator i = extractors.iterator(); i.hasNext();) {
- ContentExtractor extractor = (ContentExtractor)i.next();
- doc.add(textField(Index.CONTENT_FIELD_NAME,
- extractor.extract(content)));
- }
- } catch (ExtractorException e) {
- throw new IndexException(e);
- }
+ for(Iterator i = extractors.iterator(); i.hasNext();) {
+ ContentExtractor extractor = (ContentExtractor)i.next();
+ doc.add(textField(Index.CONTENT_FIELD_NAME,
+ extractor.extract(content)));
+ }
return doc;
}
@@ -359,35 +356,52 @@
synchronized void executeIndexTransaction(Set removeJobs, Set addJobs)
throws IndexException {
+
+ IndexWriter writer = null;
+ IndexReader reader = null;
try {
// execute delete jobs
if (removeJobs.size() > 0) {
- IndexReader reader = IndexReader.open(getDirectory());
+ reader = IndexReader.open(getDirectory());
for(Iterator i = removeJobs.iterator(); i.hasNext();) {
IndexJob job = (IndexJob)i.next();
- logger.log("remove: " + job.key, LOG_CHANNEL,
Logger.DEBUG);
+ if (logger.isEnabled(LOG_CHANNEL, Logger.DEBUG)) {
+ logger.log("remove: " + job.key, LOG_CHANNEL,
Logger.DEBUG);
+ }
reader.delete(new Term(Index.KEY_FIELD_NAME,
job.getKey()));
this.jobCounter++;
}
reader.close();
+ reader = null;
}
// execute index jobs
if (addJobs.size() > 0 || this.jobCounter >=
configuration.getOptimizeThreshold()) {
- IndexWriter writer = new IndexWriter(getDirectory(),
- configuration.getAnalyzer(), false);
+ writer = new IndexWriter(getDirectory(),
+ configuration.getAnalyzer(), false);
for(Iterator i = addJobs.iterator(); i.hasNext(); ) {
IndexJob job = (IndexJob)i.next();
Document doc;
if (job.content != null) {
- logger.log("index content: " + job.key, LOG_CHANNEL,
Logger.DEBUG);
- doc = createLuceneDocument(job.uri, job.descriptor,
job.content);
+ if (logger.isEnabled(LOG_CHANNEL, Logger.DEBUG)) {
+ logger.log("index content: " + job.key,
LOG_CHANNEL, Logger.DEBUG);
+ }
+ try {
+ doc = createLuceneDocument(job.uri,
job.descriptor, job.content);
+ writer.addDocument(doc);
+ } catch(ExtractorException e) {
+ logger.log("Error while extracting content: " +
job.uri +
+ " (" + e.toString() + ")",
+ LOG_CHANNEL, Logger.WARNING);
+ }
} else {
- logger.log("index properties: " + job.key,
LOG_CHANNEL, Logger.DEBUG);
+ if (logger.isEnabled(LOG_CHANNEL, Logger.DEBUG)) {
+ logger.log("index properties: " + job.key,
LOG_CHANNEL, Logger.DEBUG);
+ }
doc = createLuceneDocument(job.uri, job.descriptor);
+ writer.addDocument(doc);
}
- writer.addDocument(doc);
this.jobCounter++;
}
if (this.jobCounter > configuration.getOptimizeThreshold()) {
@@ -396,9 +410,17 @@
this.jobCounter = 0;
}
writer.close();
+ writer = null;
}
} catch (Exception e) {
throw new IndexException(e);
+ } finally {
+ try {
+ if (reader != null) reader.close();
+ if (writer != null) writer.close();
+ } catch (IOException e) {
+ logger.log("Exception after executeIndexTransaction", e,
LOG_CHANNEL, Logger.ERROR);
+ }
}
}
1.7 +55 -18
jakarta-slide/src/stores/org/apache/slide/index/lucene/IndexConfiguration.java
Index: IndexConfiguration.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/IndexConfiguration.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- IndexConfiguration.java 29 Nov 2004 18:38:46 -0000 1.6
+++ IndexConfiguration.java 7 Dec 2004 17:49:57 -0000 1.7
@@ -41,6 +41,7 @@
import org.apache.lucene.analysis.SimpleAnalyzer;
import org.apache.lucene.analysis.TokenStream;
+import org.apache.slide.common.PropertyName;
import org.apache.slide.content.NodeRevisionNumber;
import org.apache.slide.search.IndexException;
import org.apache.slide.util.conf.Configuration;
@@ -70,56 +71,78 @@
protected int priority = Thread.NORM_PRIORITY;
public void addStringProperty(String namespace, String name) {
- String key = namespace + name;
+ PropertyName key = PropertyName.getPropertyName(name, namespace);
this.stringProperties.add(key);
this.indexedProperties.add(key);
}
+ public boolean isStringProperty(PropertyName propertyName) {
+ return this.stringProperties.contains(propertyName);
+ }
public boolean isStringProperty(String namespace, String name) {
- return this.stringProperties.contains(namespace + name);
+ PropertyName key = PropertyName.getPropertyName(name, namespace);
+ return this.stringProperties.contains(key);
}
public void addDateProperty(String namespace, String name) {
- String key = namespace + name;
+ PropertyName key = PropertyName.getPropertyName(name, namespace);
this.dateProperties.add(key);
this.indexedProperties.add(key);
}
+ public boolean isDateProperty(PropertyName propertyName) {
+ return this.dateProperties.contains(propertyName);
+ }
public boolean isDateProperty(String namespace, String name) {
- return this.dateProperties.contains(namespace + name);
+ PropertyName key = PropertyName.getPropertyName(name, namespace);
+ return this.dateProperties.contains(key);
}
public void addIntProperty(String namespace, String name) {
- String key = namespace + name;
+ PropertyName key = PropertyName.getPropertyName(name, namespace);
this.intProperties.add(key);
this.indexedProperties.add(key);
}
+ public boolean isIntProperty(PropertyName propertyName) {
+ return this.intProperties.contains(propertyName);
+ }
public boolean isIntProperty(String namespace, String name) {
- return this.intProperties.contains(namespace + name);
+ PropertyName key = PropertyName.getPropertyName(name, namespace);
+ return this.intProperties.contains(key);
}
public void addSupportsIsdefinedProperty(String namespace, String name) {
- String key = namespace + name;
+ PropertyName key = PropertyName.getPropertyName(name, namespace);
this.supportsIsdefinedProperties.add(key);
this.indexedProperties.add(key);
}
+ public boolean supportsIsDefined(PropertyName propertyName) {
+ return this.supportsIsdefinedProperties.contains(propertyName);
+ }
public boolean supportsIsDefined(String namespace, String name) {
- return this.supportsIsdefinedProperties.contains(namespace + name);
+ PropertyName key = PropertyName.getPropertyName(name, namespace);
+ return this.supportsIsdefinedProperties.contains(key);
}
public void addTextProperty(String namespace, String name, Analyzer
analyzer) {
- String key = namespace + name;
+ PropertyName key = PropertyName.getPropertyName(name, namespace);
this.textProperties.put(key, analyzer);
this.indexedProperties.add(key);
}
-
+ public boolean isTextProperty(PropertyName propertyName) {
+ return this.textProperties.containsKey(propertyName);
+ }
public boolean isTextProperty(String namespace, String name) {
- return this.textProperties.containsKey(namespace + name);
+ PropertyName key = PropertyName.getPropertyName(name, namespace);
+ return this.textProperties.containsKey(key);
}
-
+ public boolean isIndexedProperty(PropertyName name) {
+ return this.indexedProperties.contains(name);
+ }
public boolean isIndexedProperty(String namespace, String name) {
- return this.indexedProperties.contains(namespace + name);
+ PropertyName key = PropertyName.getPropertyName(name, namespace);
+ return this.indexedProperties.contains(key);
}
/**
@@ -129,12 +152,16 @@
* @return
*/
public boolean isComparableProperty(String namespace, String name) {
- String key = namespace + name;
+ PropertyName key = PropertyName.getPropertyName(name, namespace);
return this.stringProperties.contains(key) ||
this.intProperties.contains(key) ||
this.dateProperties.contains(key);
}
-
+ public boolean isComparableProperty(PropertyName name) {
+ return this.stringProperties.contains(name) ||
+ this.intProperties.contains(name) ||
+ this.dateProperties.contains(name);
+ }
public int getOptimizeThreshold() {
return this.optimizeThreshold;
@@ -341,7 +368,17 @@
}
}
+ public String predecessor(String field, String value) {
+ StringBuffer b = new StringBuffer(value);
+ b.setCharAt(b.length()-1, (char)(b.charAt(b.length()-1)-1));
+ return b.toString();
+ }
+ public String successor(String field, String value) {
+ StringBuffer b = new StringBuffer(value);
+ b.setCharAt(b.length()-1, (char)(b.charAt(b.length()-1)+1));
+ return b.toString();
+ }
class AnalyzerImpl extends Analyzer {
Analyzer defaultAnalyzer = new SimpleAnalyzer();
Analyzer contentAnalyzer = null;
1.7 +5 -5
jakarta-slide/src/stores/org/apache/slide/index/lucene/LuceneExpressionFactory.java
Index: LuceneExpressionFactory.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/LuceneExpressionFactory.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- LuceneExpressionFactory.java 29 Nov 2004 18:39:37 -0000 1.6
+++ LuceneExpressionFactory.java 7 Dec 2004 17:49:57 -0000 1.7
@@ -258,12 +258,12 @@
// TODO not-between
if (operator.equals("between")) {
if (configuration.isComparableProperty(namespace, name)) {
- return new BetweenExpression(this.index, e, false);
+ return new BetweenExpression(this.index, e, false, false);
}
}
if (operator.equals("between-inclusive")) {
if (configuration.isComparableProperty(namespace, name)) {
- return new BetweenExpression(this.index, e, true);
+ return new BetweenExpression(this.index, e, true, false);
}
}
if (operator.equals("property-contains")) {
1.5 +2 -2
jakarta-slide/src/stores/org/apache/slide/index/lucene/LucenePropertiesIndexer.java
Index: LucenePropertiesIndexer.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/LucenePropertiesIndexer.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- LucenePropertiesIndexer.java 8 Nov 2004 09:45:10 -0000 1.4
+++ LucenePropertiesIndexer.java 7 Dec 2004 17:49:57 -0000 1.5
@@ -128,14 +128,14 @@
// removed properties is to be indexed
for(Enumeration e =
revisionDescriptor.enumerateUpdatedProperties();e.hasMoreElements();) {
NodeProperty property = (NodeProperty)e.nextElement();
-
if(index.getConfiguration().isIndexedProperty(property.getNamespace(),
property.getName())) {
+
if(index.getConfiguration().isIndexedProperty(property.getPropertyName())) {
needsUpdate = true;
break;
}
}
for(Enumeration e =
revisionDescriptor.enumerateRemovedProperties();!needsUpdate &&
e.hasMoreElements();) {
NodeProperty property = (NodeProperty)e.nextElement();
-
if(index.getConfiguration().isIndexedProperty(property.getNamespace(),
property.getName())) {
+
if(index.getConfiguration().isIndexedProperty(property.getPropertyName())) {
needsUpdate = true;
break;
}
1.2 +18 -10
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/AbstractLuceneExpression.java
Index: AbstractLuceneExpression.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/AbstractLuceneExpression.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- AbstractLuceneExpression.java 29 Nov 2004 18:38:16 -0000 1.1
+++ AbstractLuceneExpression.java 7 Dec 2004 17:49:57 -0000 1.2
@@ -90,7 +90,6 @@
{
this.factory = (LuceneExpressionFactory)factory;
}
-
public IBasicResultSet execute() throws SearchException
{
@@ -109,9 +108,10 @@
// add a scope restriction, this allows negated queries too
BooleanQuery booleanQuery = new BooleanQuery();
+ booleanQuery.add(luceneQuery, true, false);
booleanQuery.add(new TermQuery(new Term(Index.SCOPE_FIELD_NAME,
scope)),
true, false);
- booleanQuery.add(luceneQuery, true, false);
+
// add depth restriction
switch (q.getScope().getDepth() ) {
case QueryScope.DEPTH_INFINITY:
@@ -137,15 +137,19 @@
IndexSearcher searcher = null;
try {
- index.getLogger().log("start query execution: " +
- luceneQuery.toString(), LOG_CHANNEL, Logger.DEBUG);
+ if (index.getLogger().isEnabled(LOG_CHANNEL, Logger.DEBUG)) {
+ index.getLogger().log("start query execution: " +
+ luceneQuery.toString(), LOG_CHANNEL, Logger.DEBUG);
+ }
long start = System.currentTimeMillis();
searcher = this.index.getSearcher();
Hits hits = searcher.search(luceneQuery);
- index.getLogger().log("finished: " + hits.length() + " hits (" +
- (System.currentTimeMillis() - start) + "ms)" ,
LOG_CHANNEL, Logger.DEBUG);
+ if (index.getLogger().isEnabled(LOG_CHANNEL, Logger.DEBUG)) {
+ index.getLogger().log("finished: " + hits.length() + " hits
(" +
+ (System.currentTimeMillis() - start) + "ms)" ,
LOG_CHANNEL, Logger.DEBUG);
+ }
IBasicResultSet result = new BasicResultSetImpl(false);
@@ -183,12 +187,16 @@
protected Query negateQuery(Query query) {
BooleanQuery booleanQuery = new BooleanQuery();
booleanQuery.add(
- new TermQuery(new Term(Index.SCOPE_FIELD_NAME, "/")),
+ allQuery(),
true, false);
booleanQuery.add(
query,
false, true);
return booleanQuery;
+ }
+
+ protected Query allQuery() {
+ return new TermQuery(new Term(Index.SCOPE_FIELD_NAME, "/"));
}
protected RequestedResource createResource(String uri) throws
SearchException
1.6 +67 -12
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/BetweenExpression.java
Index: BetweenExpression.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/BetweenExpression.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- BetweenExpression.java 29 Nov 2004 18:38:16 -0000 1.5
+++ BetweenExpression.java 7 Dec 2004 17:49:57 -0000 1.6
@@ -23,6 +23,8 @@
package org.apache.slide.index.lucene.expressions;
import org.apache.lucene.index.Term;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Query;
import org.apache.lucene.search.RangeQuery;
import org.apache.lucene.search.TermQuery;
@@ -37,10 +39,11 @@
* <code>between-inclusive</code> operators.
*
* <p>
- * With lucene <code>(between prop val1 val2)</code> will be much more
efficient
+ * With lucene <code>(between prop val1 val2)</code> will be more efficient
* than <code>(and (gt prop1 val1) (lt prop val2))</code>.
- *
- * <p>TODO May be we could optimize such expressions by transformation.
+ * <br>
+ * In the [EMAIL PROTECTED]
org.apache.slide.index.lucene.expressions.MergeExpression}
+ * such an optimization is implemented.
*
* <p>Usage:
* <pre>
@@ -55,7 +58,7 @@
public class BetweenExpression extends AbstractLuceneExpression
{
- public BetweenExpression(Index index, Element element, boolean inclusive)
+ public BetweenExpression(Index index, Element element, boolean
inclusive, boolean negated)
throws BadQueryException
{
super(index);
@@ -83,23 +86,75 @@
value2 = literal2.getTextTrim();
}
+ if (negated) {
+ setQuery(createQuery(field, value1, value2, !inclusive));
+ negateQuery(field);
+ } else {
+ setQuery(createQuery(field, value1, value2, inclusive));
+ }
+ }
+
+ public BetweenExpression(Index index, String field, String lowerValue,
+ String upperValue, boolean incluseLower, boolean incluseUpper,
+ boolean negated) {
+ super(index);
+ if (incluseLower == incluseUpper) {
+ if (negated) {
+ setQuery(createQuery(field, lowerValue, upperValue,
!incluseLower));
+ negateQuery(field);
+ } else {
+ setQuery(createQuery(field, lowerValue, upperValue,
incluseLower));
+ }
+ } else {
+ // TODO what about negative integer values
(predecessor,successor
+ // does not work with this)
+ if (incluseLower) {
+ setQuery(createQuery(field,
+ lowerValue,
+ index.getConfiguration().predecessor(field,
upperValue),
+ true));
+ } else {
+ setQuery(createQuery(field,
+ index.getConfiguration().successor(field,
lowerValue),
+ upperValue,
+ true));
+ }
+ }
+ }
+
+ private void negateQuery(String field)
+ {
+ BooleanQuery booleanQuery = new BooleanQuery();
+ booleanQuery.add(
+ new TermQuery(new Term(Index.IS_DEFINED_FIELD_NAME, field)),
+ true, // required
+ false);
+ booleanQuery.add(getQuery(),
+ false,
+ true); // prohibited
+ setQuery(booleanQuery);
+ }
+
+ private Query createQuery(String field, String value1, String value2,
boolean inclusive)
+ {
int comp = value1.compareTo(value2);
if (comp == 0) {
// value1 == value2
- setQuery(new TermQuery(new Term(field, value1)));
+ return new TermQuery(new Term(field, value1));
} else if (comp < 0) {
// value1 < value2
- setQuery(new RangeQuery(
+ return new RangeQuery(
new Term(field, value1),
new Term(field, value2),
- inclusive)); // inclusive or not
+ inclusive); // inclusive or not
} else {
// value1 > value2
- setQuery(new RangeQuery(
+ return new RangeQuery(
new Term(field, value2),
new Term(field, value1),
- inclusive)); // inclusive or not
+ inclusive); // inclusive or not
}
}
+
}
1.3 +4 -3
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/ContainsExpression.java
Index: ContainsExpression.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/ContainsExpression.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ContainsExpression.java 29 Nov 2004 18:38:16 -0000 1.2
+++ ContainsExpression.java 7 Dec 2004 17:49:57 -0000 1.3
@@ -70,6 +70,7 @@
termOrPhraseQuery(config, Index.CONTENT_FIELD_NAME, literal);
}
+ // TODO
if (negated) {
setQuery(negateQuery(getQuery()));
}
1.7 +47 -22
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/GtExpression.java
Index: GtExpression.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/GtExpression.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- GtExpression.java 29 Nov 2004 18:38:16 -0000 1.6
+++ GtExpression.java 7 Dec 2004 17:49:57 -0000 1.7
@@ -35,40 +35,65 @@
/**
* Implements <code>gt</code> and <code>gte</code> expression.
*/
-public class GtExpression extends AbstractLuceneExpression
+public class GtExpression extends AbstractLuceneExpression implements
RangeOperator
{
- public GtExpression(Index index, Element element, boolean inclusive)
- throws BadQueryException
+ private String field;
+ private String value;
+ private boolean inclusive;
+
+ public GtExpression(Index index, Element element, boolean inclusive)
+ throws BadQueryException
{
super(index);
+ this.inclusive = inclusive;
IndexConfiguration config = index.getConfiguration();
Element prop = getPropertyElement(element);
- String field = config.generateFieldName(prop.getNamespaceURI(),
prop.getName());
+ this.field = config.generateFieldName(prop.getNamespaceURI(),
prop.getName());
Element literal = getLiteralElement(element);
- String value;
String upperBound;
if (index.getConfiguration().isDateProperty(prop.getNamespaceURI(),
prop.getName())) {
Date date =
IndexConfiguration.getDateValue(literal.getTextTrim());
- value = config.dateToIndexString(date);
+ this.value = config.dateToIndexString(date);
upperBound = Index.DATE_UPPER_BOUND;
- }
- else if
(index.getConfiguration().isIntProperty(prop.getNamespaceURI(),
prop.getName())) {
- value =
config.intToIndexString(Long.parseLong(literal.getTextTrim()));
+ } else if
(index.getConfiguration().isIntProperty(prop.getNamespaceURI(),
prop.getName())) {
+ this.value =
config.intToIndexString(Long.parseLong(literal.getTextTrim()));
upperBound = Index.INT_UPPER_BOUND;
- }
- else {
- value = literal.getTextTrim();
+ } else {
+ this.value = literal.getTextTrim();
upperBound = Index.STRING_UPPER_BOUND;
}
-
-
+
RangeQuery rangeQuery = new RangeQuery(
- new Term(field, value),
- new Term(field, upperBound),
- inclusive); // inclusive or not
-
+ new Term(this.field, this.value),
+ new Term(this.field, upperBound),
+ inclusive); // inclusive or not
+
setQuery(rangeQuery);
}
-}
+
+ public String getField() {
+ return this.field;
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+ public boolean inclusive() {
+ return this.inclusive;
+ }
+
+ public String toString() {
+ StringBuffer b = new StringBuffer();
+
+ b.append('(')
+ .append(this.field)
+ .append('>')
+ .append(this.inclusive ? "=" : "")
+ .append(this.value)
+ .append(')');
+
+ return b.toString();
+ }
+}
\ No newline at end of file
1.4 +4 -4
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/IsCollectionExpression.java
Index: IsCollectionExpression.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/IsCollectionExpression.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- IsCollectionExpression.java 29 Nov 2004 18:38:16 -0000 1.3
+++ IsCollectionExpression.java 7 Dec 2004 17:49:57 -0000 1.4
@@ -43,7 +43,7 @@
setQuery(new TermQuery(new Term(config.generateFieldName(
NodeProperty.DEFAULT_NAMESPACE, "resourcetype"),
"collection")));
-
+
if (negated) {
setQuery(negateQuery(getQuery()));
}
1.6 +12 -8
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/IsDefinedExpression.java
Index: IsDefinedExpression.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/IsDefinedExpression.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- IsDefinedExpression.java 29 Nov 2004 18:38:16 -0000 1.5
+++ IsDefinedExpression.java 7 Dec 2004 17:49:57 -0000 1.6
@@ -37,7 +37,6 @@
*/
public class IsDefinedExpression extends AbstractLuceneExpression
{
-
public IsDefinedExpression(Index index, Element element, boolean
negated)
throws BadQueryException
{
@@ -47,11 +46,16 @@
Element prop = getPropertyElement(element);
String field = config.generateFieldName(prop.getNamespaceURI(),
prop.getName());
-
- if (config.supportsIsDefined(prop.getNamespaceURI(),
prop.getName())) {
- setQuery(new TermQuery(new Term(Index.IS_DEFINED_FIELD_NAME,
field)));
+ setQuery(new TermQuery(new Term(Index.IS_DEFINED_FIELD_NAME,
field)));
+ if (negated) {
+ setQuery(negateQuery(getQuery()));
}
-
+ }
+
+ public IsDefinedExpression(Index index, String field, boolean negated) {
+ super(index);
+
+ setQuery(new TermQuery(new Term(Index.IS_DEFINED_FIELD_NAME,
field)));
if (negated) {
setQuery(negateQuery(getQuery()));
}
1.5 +14 -4
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/LikeExpression.java
Index: LikeExpression.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/LikeExpression.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- LikeExpression.java 29 Nov 2004 18:38:16 -0000 1.4
+++ LikeExpression.java 7 Dec 2004 17:49:57 -0000 1.5
@@ -23,7 +23,9 @@
package org.apache.slide.index.lucene.expressions;
import org.apache.lucene.index.Term;
+import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.PrefixQuery;
+import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.WildcardQuery;
import org.apache.lucene.search.WildcardTermEnum;
@@ -63,7 +65,15 @@
}
if (negated) {
- setQuery(negateQuery(getQuery()));
+ BooleanQuery booleanQuery = new BooleanQuery();
+ booleanQuery.add(
+ new TermQuery(new Term(Index.IS_DEFINED_FIELD_NAME,
field)),
+ true, // required
+ false);
+ booleanQuery.add(getQuery(),
+ false,
+ true); // prohibited
+ setQuery(booleanQuery);
}
}
1.6 +39 -11
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/LtExpression.java
Index: LtExpression.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/LtExpression.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- LtExpression.java 29 Nov 2004 18:38:16 -0000 1.5
+++ LtExpression.java 7 Dec 2004 17:49:57 -0000 1.6
@@ -36,44 +36,72 @@
/**
* Implements <code>lt</code> and <code>lte</code> expression.
*/
-public class LtExpression extends AbstractLuceneExpression
+public class LtExpression extends AbstractLuceneExpression implements
RangeOperator
{
+ private String field;
+ private String value;
+ private boolean inclusive;
public LtExpression(Index index, Element element, boolean inclusive)
throws BadQueryException
{
super(index);
+ this.inclusive = inclusive;
IndexConfiguration config = index.getConfiguration();
Element prop = getPropertyElement(element);
- String field = config.generateFieldName(prop.getNamespaceURI(),
prop.getName());
+ this.field = config.generateFieldName(prop.getNamespaceURI(),
prop.getName());
Element literal = getLiteralElement(element);
- String value;
String lowerBound;
if (index.getConfiguration().isDateProperty(prop.getNamespaceURI(),
prop.getName())) {
Date date =
IndexConfiguration.getDateValue(literal.getTextTrim());
Calendar c = Calendar.getInstance();
c.setTime(date);
inclusive = c.get(Calendar.SECOND) > 0;
- value = config.dateToIndexString(date);
+ this.value = config.dateToIndexString(date);
lowerBound = Index.DATE_LOWER_BOUND;
}
else if
(index.getConfiguration().isIntProperty(prop.getNamespaceURI(),
prop.getName())) {
- value =
config.intToIndexString(Long.parseLong(literal.getTextTrim()));
+ this.value =
config.intToIndexString(Long.parseLong(literal.getTextTrim()));
lowerBound = Index.INT_LOWER_BOUND;
}
else {
- value = literal.getTextTrim();
+ this.value = literal.getTextTrim();
lowerBound = Index.STRING_LOWER_BOUND;
}
RangeQuery rangeQuery = new RangeQuery(
- new Term(field, lowerBound),
- new Term(field, value),
+ new Term(this.field, lowerBound),
+ new Term(this.field, this.value),
inclusive); // inclusive or not
setQuery(rangeQuery);
+ }
+
+ public String getField() {
+ return this.field;
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+
+ public boolean inclusive() {
+ return this.inclusive;
+ }
+
+ public String toString() {
+ StringBuffer b = new StringBuffer();
+
+ b.append('(')
+ .append(this.field)
+ .append('<')
+ .append(this.inclusive ? "=" : "")
+ .append(this.value)
+ .append(')');
+
+ return b.toString();
}
}
1.4 +161 -9
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/MergeExpression.java
Index: MergeExpression.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/MergeExpression.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- MergeExpression.java 29 Nov 2004 18:39:38 -0000 1.3
+++ MergeExpression.java 7 Dec 2004 17:49:57 -0000 1.4
@@ -22,8 +22,12 @@
*/
package org.apache.slide.index.lucene.expressions;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Query;
@@ -47,14 +51,162 @@
{
super(index);
- BooleanQuery booleanQuery = new BooleanQuery();
+ expressions = optimizeRanges(and, expressions);
- for(Iterator i = expressions.iterator(); i.hasNext();) {
- Object e = i.next();
- Query q = ((AbstractLuceneExpression)e).getQuery();
- booleanQuery.add(q, and, false);
+ if (expressions.size() == 1) {
+ AbstractLuceneExpression expression =
+ (AbstractLuceneExpression)expressions.iterator().next();
+ setQuery(expression.getQuery());
+
+ } else {
+ BooleanQuery booleanQuery = new BooleanQuery();
+
+ for(Iterator i = expressions.iterator(); i.hasNext();) {
+ Object e = i.next();
+ AbstractLuceneExpression expression =
(AbstractLuceneExpression)e;
+ Query q = expression.getQuery();
+ booleanQuery.add(q, and, false);
+ }
+ setQuery(booleanQuery);
+ }
+ }
+
+ private Collection optimizeRanges(boolean and, Collection expressions) {
+ Map fields = new HashMap();
+ List result = new ArrayList(expressions.size());
+
+ // search for comparision operators that work on same field
+
+ for (Iterator i = expressions.iterator(); i.hasNext();) {
+ Object o = i.next();
+ if (o instanceof RangeOperator) {
+ RangeOperator op = (RangeOperator)o;
+
+ List ops = (List)fields.get(op.getField());
+ if (ops == null) {
+ ops = new ArrayList();
+ fields.put(op.getField(), ops);
+ }
+ ops.add(op);
+ } else {
+ result.add(o);
+ }
+ }
+
+ for (Iterator i = fields.entrySet().iterator(); i.hasNext();) {
+ Map.Entry e = (Map.Entry)i.next();
+ List ops = (List)e.getValue();
+
+ if (ops.size() == 2) {
+ AbstractLuceneExpression expr = optBetween(
+ (RangeOperator)ops.get(0),
+ (RangeOperator)ops.get(1), and);
+ if (expr != null) {
+ result.add(expr);
+ }
+ } else {
+ result.addAll(ops);
+ }
}
- setQuery(booleanQuery);
+ return result;
+ }
+
+ private AbstractLuceneExpression optBetween(RangeOperator o1,
RangeOperator o2, boolean and) {
+ if (o1 instanceof GtExpression) {
+ if (o2 instanceof LtExpression) {
+ if (and) {
+ if (o1.getValue().compareTo(o2.getValue()) <= 0) {
+ // ------o1>++++++<o2------
+ return new BetweenExpression(this.index,
o1.getField(),
+ o1.getValue(), o2.getValue(),
+ o1.inclusive(), o2.inclusive(),
+ false);
+ } else {
+ // ------<o2------o1>------
+ return null;
+ }
+ } else {
+ if (o1.getValue().compareTo(o2.getValue()) >= 0) {
+ // ++++++<o2------o1>++++++
+ return new BetweenExpression(this.index,
o1.getField(),
+ o2.getValue(), o1.getValue(),
+ o2.inclusive(), o1.inclusive(),
+ true); // negated
+ } else {
+ // ++++++o1>+++++<o2+++++++
+ return new IsDefinedExpression(this.index,
o1.getField(), false);
+ }
+ }
+ }
+ if (o2 instanceof GtExpression) {
+ if (and) {
+ if (o1.getValue().compareTo(o2.getValue()) <= 0) {
+ // -----o1>-----o2>++++++
+ return (AbstractLuceneExpression)o2;
+ } else {
+ // -----o2>-----o1>++++++
+ return (AbstractLuceneExpression)o1;
+ }
+ } else {
+ if (o1.getValue().compareTo(o2.getValue()) <= 0) {
+ // -----o1>+++++o2>++++++
+ return (AbstractLuceneExpression)o1;
+ } else {
+ // -----o2>+++++o1>++++++
+ return (AbstractLuceneExpression)o2;
+ }
+ }
+ }
+ throw new RuntimeException();
+ }
+ if (o1 instanceof LtExpression) {
+ if (o2 instanceof GtExpression) {
+ if (and) {
+ if (o1.getValue().compareTo(o2.getValue()) <= 0) {
+ // ------<o1------o2>------
+ return null;
+ } else {
+ // ------o2>++++++<o1------
+ return new BetweenExpression(this.index,
o1.getField(),
+ o2.getValue(), o1.getValue(),
+ o2.inclusive(), o1.inclusive(),
+ false);
+ }
+ } else {
+ if (o1.getValue().compareTo(o2.getValue()) >= 0) {
+ // ++++++o2>+++++<o1++++++
+ return new IsDefinedExpression(this.index,
o1.getField(), false);
+ } else {
+ // ++++++<o1-----o2>+++++++
+ return new BetweenExpression(this.index,
o1.getField(),
+ o1.getValue(), o2.getValue(),
+ o1.inclusive(), o2.inclusive(),
+ true); // negated
+ }
+ }
+ }
+ if (o2 instanceof LtExpression) {
+ if (and) {
+ if (o1.getValue().compareTo(o2.getValue()) <= 0) {
+ // +++++<o1-----<o2------
+ return (AbstractLuceneExpression)o1;
+ } else {
+ // +++++<o2-----<o1------
+ return (AbstractLuceneExpression)o2;
+ }
+ } else {
+ if (o1.getValue().compareTo(o2.getValue()) <= 0) {
+ // +++++<o1+++++<o2------
+ return (AbstractLuceneExpression)o2;
+ } else {
+ // +++++<o2+++++<o1------
+ return (AbstractLuceneExpression)o1;
+ }
+ }
+ }
+ throw new RuntimeException();
+ }
+ throw new RuntimeException();
}
}
1.5 +14 -4
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/PropcontainsExpression.java
Index: PropcontainsExpression.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/PropcontainsExpression.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- PropcontainsExpression.java 29 Nov 2004 18:38:16 -0000 1.4
+++ PropcontainsExpression.java 7 Dec 2004 17:49:57 -0000 1.5
@@ -23,6 +23,8 @@
package org.apache.slide.index.lucene.expressions;
import org.apache.lucene.index.Term;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.WildcardQuery;
import org.apache.slide.index.lucene.Index;
@@ -54,7 +56,15 @@
setQuery(new WildcardQuery(new Term(field, "*" + text + "*")));
if (negated) {
- setQuery(negateQuery(getQuery()));
+ BooleanQuery booleanQuery = new BooleanQuery();
+ booleanQuery.add(
+ new TermQuery(new Term(Index.IS_DEFINED_FIELD_NAME,
field)),
+ true, // required
+ false);
+ booleanQuery.add(getQuery(),
+ false,
+ true); // prohibited
+ setQuery(booleanQuery);
}
}
}
1.5 +12 -4
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/PropertyContainsExpression.java
Index: PropertyContainsExpression.java
===================================================================
RCS file:
/home/cvs/jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/PropertyContainsExpression.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- PropertyContainsExpression.java 29 Nov 2004 18:38:16 -0000 1.4
+++ PropertyContainsExpression.java 7 Dec 2004 17:49:57 -0000 1.5
@@ -75,7 +75,15 @@
}
if (negated) {
- setQuery(negateQuery(getQuery()));
+ BooleanQuery booleanQuery = new BooleanQuery();
+ booleanQuery.add(
+ new TermQuery(new Term(Index.IS_DEFINED_FIELD_NAME,
field)),
+ true, // required
+ false);
+ booleanQuery.add(getQuery(),
+ false,
+ true); // prohibited
+ setQuery(booleanQuery);
}
}
1.1
jakarta-slide/src/stores/org/apache/slide/index/lucene/expressions/RangeOperator.java
Index: RangeOperator.java
===================================================================
// vi: set ts=3 sw=3:
package org.apache.slide.index.lucene.expressions;
/**
* @author Stefan L�tzkendorf
*/
interface RangeOperator
{
public String getField();
public String getValue();
public boolean inclusive();
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]