This will find documents whose mod_date fields have values between 20020101 and 20030101, inclusive.
Note that Range Queries are not reserved for date fields. You could also use range queries with non-date fields:
title:{Aida TO Carmen}
-
This will find all documents whose titles are between Aida and Carmen, but not including Aida and Carmen.
-
Inclusive range queries are denoted by square brackets. Exclusive range queries are denoted by
+
This will find all documents whose titles are between Aida and Carmen, but not including Aida and Carmen.
+ Note that Range Queries need not be solely inclusive or exclusive:
+
firstName:[Bob TO Mike}
+
This will find all documents whose firstName fields have values between Bob and Mike, including Bob but not Mike.
+
Inclusive range query bounds are denoted by square brackets. Exclusive range query bounds are denoted by
curly brackets.
-
+
Boosting a Term
Lucene provides the relevance level of matching documents based on the terms found. To boost a term use the caret, "^", symbol with a boost factor (a number) at the end of the term you are searching. The higher the boost factor, the more relevant the term will be.
Boosting allows you to control the relevance of a document by boosting its term. For example, if you are searching for
@@ -433,12 +436,12 @@
-
+
Boolean Operators
Boolean operators allow terms to be combined through logic operators.
Lucene supports AND, "+", OR, NOT and "-" as Boolean operators(Note: Boolean operators must be ALL CAPS).
-
+
The OR operator is the default conjunction operator. This means that if there is no Boolean operator between two terms, the OR operator is used.
The OR operator links two terms and finds a matching document if either of the terms exist in a document. This is equivalent to a union using sets.
@@ -447,18 +450,18 @@
"jakarta apache" jakarta
or
"jakarta apache" OR jakarta
-
+
AND
The AND operator matches documents where both terms exist anywhere in the text of a single document.
This is equivalent to an intersection using sets. The symbol && can be used in place of the word AND.
To search for documents that contain "jakarta apache" and "Apache Lucene" use the query:
"jakarta apache" AND "Apache Lucene"
-
+
+
The "+" or required operator requires that the term after the "+" symbol exist somewhere in a the field of a single document.
To search for documents that must contain "jakarta" and may contain "lucene" use the query:
+jakarta lucene
-
+
NOT
The NOT operator excludes documents that contain the term after NOT.
This is equivalent to a difference using sets. The symbol ! can be used in place of the word NOT.
@@ -466,7 +469,7 @@
"jakarta apache" NOT "Apache Lucene"
Note: The NOT operator cannot be used with just one term. For example, the following search will return no results:
NOT "jakarta apache"
-
+
-
The "-" or prohibit operator excludes documents that contain the term after the "-" symbol.
To search for documents that contain "jakarta apache" but not "Apache Lucene" use the query:
@@ -474,7 +477,7 @@
-
+
Grouping
Lucene supports using parentheses to group clauses to form sub queries. This can be very useful if you want to control the boolean logic for a query.
@@ -484,7 +487,7 @@
-
+
Field Grouping
Lucene supports using parentheses to group multiple clauses to a single field.
@@ -493,7 +496,7 @@
-
+
Escaping Special Characters
Lucene supports escaping special characters that are part of the query syntax. The current list special characters are
*
@@ -528,12 +528,16 @@
/**
* @exception ParseException throw in overridden method to disallow
+ * @deprecated This method has been deprecated in order to conform to the
+ * updated range query syntax. Update code to use
+ * {@link #getRangeQuery(String, String, String, boolean, boolean)}.
*/
protected Query getRangeQuery(String field,
String part1,
String part2,
boolean inclusive) throws ParseException
{
+ // Allow code duplication here in order not to break the old API
if (lowercaseExpandedTerms) {
part1 = part1.toLowerCase();
part2 = part2.toLowerCase();
@@ -582,6 +586,72 @@
}
/**
+ * @exception ParseException throw in overridden method to disallow
+ */
+ protected Query getRangeQuery(String field,
+ String part1,
+ String part2,
+ boolean startInclusive,
+ boolean endInclusive) throws ParseException
+ {
+ if (startInclusive & endInclusive) {
+ // Use the old method for the time being while it's still apart of the API
+ return getRangeQuery(field, part1, part2, true);
+ }
+
+ if ((startInclusive ^ endInclusive) && useOldRangeQuery) {
+ throw new ParseException("Cannot mix inclusive/exclusive on range query"
+ + " with useOldRangeQuery=true");
+ }
+
+ if (lowercaseExpandedTerms) {
+ part1 = part1.toLowerCase();
+ part2 = part2.toLowerCase();
+ }
+ try {
+ DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
+ df.setLenient(true);
+ Date d1 = df.parse(part1);
+ Date d2 = df.parse(part2);
+ if (endInclusive) {
+ // The user can only specify the date, not the time, so make sure
+ // the time is set to the latest possible time of that date to really
+ // include all documents:
+ Calendar cal = Calendar.getInstance(locale);
+ cal.setTime(d2);
+ cal.set(Calendar.HOUR_OF_DAY, 23);
+ cal.set(Calendar.MINUTE, 59);
+ cal.set(Calendar.SECOND, 59);
+ cal.set(Calendar.MILLISECOND, 999);
+ d2 = cal.getTime();
+ }
+ DateTools.Resolution resolution = getDateResolution(field);
+ if (resolution == null) {
+ // no default or field specific date resolution has been set,
+ // use deprecated DateField to maintain compatibilty with
+ // pre-1.9 Lucene versions.
+ part1 = DateField.dateToString(d1);
+ part2 = DateField.dateToString(d2);
+ } else {
+ part1 = DateTools.dateToString(d1, resolution);
+ part2 = DateTools.dateToString(d2, resolution);
+ }
+ }
+ catch (Exception e) { }
+
+ if(useOldRangeQuery)
+ {
+ return new RangeQuery(new Term(field, part1),
+ new Term(field, part2),
+ startInclusive & endInclusive);
+ }
+ else
+ {
+ return new ConstantScoreRangeQuery(field,part1,part2,startInclusive,endInclusive);
+ }
+ }
+
+ /**
* Factory method for generating query, given a set of clauses.
* By default creates a boolean query composed of clauses passed in.
*
@@ -1013,7 +1083,7 @@
}
final public Query Term(String field) throws ParseException {
- Token term, boost=null, fuzzySlop=null, goop1, goop2;
+ Token term, boost=null, fuzzySlop=null, goop1, goop2, goop3;
boolean prefix = false;
boolean wildcard = false;
boolean fuzzy = false;
@@ -1099,11 +1169,11 @@
case RANGEIN_START:
jj_consume_token(RANGEIN_START);
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case RANGEIN_GOOP:
- goop1 = jj_consume_token(RANGEIN_GOOP);
+ case RANGE_GOOP:
+ goop1 = jj_consume_token(RANGE_GOOP);
break;
- case RANGEIN_QUOTED:
- goop1 = jj_consume_token(RANGEIN_QUOTED);
+ case RANGE_QUOTED:
+ goop1 = jj_consume_token(RANGE_QUOTED);
break;
default:
jj_la1[12] = jj_gen;
@@ -1111,95 +1181,126 @@
throw new ParseException();
}
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case RANGEIN_TO:
- jj_consume_token(RANGEIN_TO);
+ case RANGE_TO:
+ jj_consume_token(RANGE_TO);
break;
default:
jj_la1[13] = jj_gen;
;
}
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case RANGEIN_GOOP:
- goop2 = jj_consume_token(RANGEIN_GOOP);
+ case RANGE_GOOP:
+ goop2 = jj_consume_token(RANGE_GOOP);
break;
- case RANGEIN_QUOTED:
- goop2 = jj_consume_token(RANGEIN_QUOTED);
+ case RANGE_QUOTED:
+ goop2 = jj_consume_token(RANGE_QUOTED);
break;
default:
jj_la1[14] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
- jj_consume_token(RANGEIN_END);
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case RANGEIN_END:
+ goop3 = jj_consume_token(RANGEIN_END);
+ break;
+ case RANGEEX_END:
+ goop3 = jj_consume_token(RANGEEX_END);
+ break;
+ default:
+ jj_la1[15] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case CARAT:
jj_consume_token(CARAT);
boost = jj_consume_token(NUMBER);
break;
default:
- jj_la1[15] = jj_gen;
+ jj_la1[16] = jj_gen;
;
}
- if (goop1.kind == RANGEIN_QUOTED) {
+ if (goop1.kind == RANGE_QUOTED) {
goop1.image = goop1.image.substring(1, goop1.image.length()-1);
}
- if (goop2.kind == RANGEIN_QUOTED) {
+ if (goop2.kind == RANGE_QUOTED) {
goop2.image = goop2.image.substring(1, goop2.image.length()-1);
}
- q = getRangeQuery(field, discardEscapeChar(goop1.image), discardEscapeChar(goop2.image), true);
+
+ if (goop3.kind == RANGEEX_END) {
+ q = getRangeQuery(field, discardEscapeChar(goop1.image), discardEscapeChar(goop2.image), true, false);
+ } else {
+ q = getRangeQuery(field, discardEscapeChar(goop1.image), discardEscapeChar(goop2.image), true, true);
+ }
break;
case RANGEEX_START:
jj_consume_token(RANGEEX_START);
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case RANGEEX_GOOP:
- goop1 = jj_consume_token(RANGEEX_GOOP);
+ case RANGE_GOOP:
+ goop1 = jj_consume_token(RANGE_GOOP);
break;
- case RANGEEX_QUOTED:
- goop1 = jj_consume_token(RANGEEX_QUOTED);
+ case RANGE_QUOTED:
+ goop1 = jj_consume_token(RANGE_QUOTED);
break;
default:
- jj_la1[16] = jj_gen;
+ jj_la1[17] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case RANGEEX_TO:
- jj_consume_token(RANGEEX_TO);
+ case RANGE_TO:
+ jj_consume_token(RANGE_TO);
break;
default:
- jj_la1[17] = jj_gen;
+ jj_la1[18] = jj_gen;
;
}
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
- case RANGEEX_GOOP:
- goop2 = jj_consume_token(RANGEEX_GOOP);
+ case RANGE_GOOP:
+ goop2 = jj_consume_token(RANGE_GOOP);
break;
- case RANGEEX_QUOTED:
- goop2 = jj_consume_token(RANGEEX_QUOTED);
+ case RANGE_QUOTED:
+ goop2 = jj_consume_token(RANGE_QUOTED);
break;
default:
- jj_la1[18] = jj_gen;
+ jj_la1[19] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
- jj_consume_token(RANGEEX_END);
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case RANGEEX_END:
+ goop3 = jj_consume_token(RANGEEX_END);
+ break;
+ case RANGEIN_END:
+ goop3 = jj_consume_token(RANGEIN_END);
+ break;
+ default:
+ jj_la1[20] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case CARAT:
jj_consume_token(CARAT);
boost = jj_consume_token(NUMBER);
break;
default:
- jj_la1[19] = jj_gen;
+ jj_la1[21] = jj_gen;
;
}
- if (goop1.kind == RANGEEX_QUOTED) {
+ if (goop1.kind == RANGE_QUOTED) {
goop1.image = goop1.image.substring(1, goop1.image.length()-1);
}
- if (goop2.kind == RANGEEX_QUOTED) {
+ if (goop2.kind == RANGE_QUOTED) {
goop2.image = goop2.image.substring(1, goop2.image.length()-1);
}
- q = getRangeQuery(field, discardEscapeChar(goop1.image), discardEscapeChar(goop2.image), false);
+ if (goop3.kind == RANGEIN_END) {
+ q = getRangeQuery(field, discardEscapeChar(goop1.image), discardEscapeChar(goop2.image), false, true);
+ } else {
+ q = getRangeQuery(field, discardEscapeChar(goop1.image), discardEscapeChar(goop2.image), false, false);
+ }
break;
case QUOTED:
term = jj_consume_token(QUOTED);
@@ -1208,7 +1309,7 @@
fuzzySlop = jj_consume_token(FUZZY_SLOP);
break;
default:
- jj_la1[20] = jj_gen;
+ jj_la1[22] = jj_gen;
;
}
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
@@ -1217,7 +1318,7 @@
boost = jj_consume_token(NUMBER);
break;
default:
- jj_la1[21] = jj_gen;
+ jj_la1[23] = jj_gen;
;
}
int s = phraseSlop;
@@ -1231,7 +1332,7 @@
q = getFieldQuery(field, discardEscapeChar(term.image.substring(1, term.image.length()-1)), s);
break;
default:
- jj_la1[22] = jj_gen;
+ jj_la1[24] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
@@ -1292,19 +1393,14 @@
public boolean lookingAhead = false;
private boolean jj_semLA;
private int jj_gen;
- final private int[] jj_la1 = new int[23];
+ final private int[] jj_la1 = new int[25];
static private int[] jj_la1_0;
- static private int[] jj_la1_1;
static {
jj_la1_0();
- jj_la1_1();
}
private static void jj_la1_0() {
- jj_la1_0 = new int[] {0x180,0x180,0xe00,0xe00,0x1f69f80,0x48000,0x10000,0x1f69000,0x1348000,0x80000,0x80000,0x10000,0x18000000,0x2000000,0x18000000,0x10000,0x80000000,0x20000000,0x80000000,0x10000,0x80000,0x10000,0x1f68000,};
+ jj_la1_0 = new int[] {0x180,0x180,0xe00,0xe00,0x1f69f80,0x48000,0x10000,0x1f69000,0x1348000,0x80000,0x80000,0x10000,0x30000000,0x2000000,0x30000000,0xc000000,0x10000,0x30000000,0x2000000,0x30000000,0xc000000,0x10000,0x80000,0x10000,0x1f68000,};
}
- private static void jj_la1_1() {
- jj_la1_1 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x1,0x0,0x0,0x0,0x0,};
- }
final private JJCalls[] jj_2_rtns = new JJCalls[1];
private boolean jj_rescan = false;
private int jj_gc = 0;
@@ -1314,7 +1410,7 @@
token = new Token();
jj_ntk = -1;
jj_gen = 0;
- for (int i = 0; i < 23; i++) jj_la1[i] = -1;
+ for (int i = 0; i < 25; i++) jj_la1[i] = -1;
for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
}
@@ -1323,7 +1419,7 @@
token = new Token();
jj_ntk = -1;
jj_gen = 0;
- for (int i = 0; i < 23; i++) jj_la1[i] = -1;
+ for (int i = 0; i < 25; i++) jj_la1[i] = -1;
for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
}
@@ -1332,7 +1428,7 @@
token = new Token();
jj_ntk = -1;
jj_gen = 0;
- for (int i = 0; i < 23; i++) jj_la1[i] = -1;
+ for (int i = 0; i < 25; i++) jj_la1[i] = -1;
for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
}
@@ -1341,7 +1437,7 @@
token = new Token();
jj_ntk = -1;
jj_gen = 0;
- for (int i = 0; i < 23; i++) jj_la1[i] = -1;
+ for (int i = 0; i < 25; i++) jj_la1[i] = -1;
for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
}
@@ -1452,27 +1548,24 @@
public ParseException generateParseException() {
jj_expentries.removeAllElements();
- boolean[] la1tokens = new boolean[33];
- for (int i = 0; i < 33; i++) {
+ boolean[] la1tokens = new boolean[30];
+ for (int i = 0; i < 30; i++) {
la1tokens[i] = false;
}
if (jj_kind >= 0) {
la1tokens[jj_kind] = true;
jj_kind = -1;
}
- for (int i = 0; i < 23; i++) {
+ for (int i = 0; i < 25; i++) {
if (jj_la1[i] == jj_gen) {
for (int j = 0; j < 32; j++) {
if ((jj_la1_0[i] & (1< jj_gen) {
@@ -1508,6 +1602,7 @@
}
p = p.next;
} while (p != null);
+ } catch(LookaheadSuccess ls) { }
}
jj_rescan = false;
}
Index: src/java/org/apache/lucene/queryParser/QueryParser.jj
===================================================================
--- src/java/org/apache/lucene/queryParser/QueryParser.jj (revision 574284)
+++ src/java/org/apache/lucene/queryParser/QueryParser.jj (working copy)
@@ -91,7 +91,7 @@
* If you use neither {@link DateField} nor {@link DateTools} in your
* index, you can create your own
* query parser that inherits QueryParser and overwrites
- * {@link #getRangeQuery(String, String, String, boolean)} to
+ * {@link #getRangeQuery(String, String, String, boolean, boolean)} to
* use a different method for date conversion.
*
*
@@ -552,12 +552,16 @@
/**
* @exception ParseException throw in overridden method to disallow
+ * @deprecated This method has been deprecated in order to conform to the
+ * updated range query syntax. Update code to use
+ * {@link #getRangeQuery(String, String, String, boolean, boolean)}.
*/
protected Query getRangeQuery(String field,
String part1,
String part2,
boolean inclusive) throws ParseException
{
+ // Allow code duplication here in order not to break the old API
if (lowercaseExpandedTerms) {
part1 = part1.toLowerCase();
part2 = part2.toLowerCase();
@@ -606,6 +610,72 @@
}
/**
+ * @exception ParseException throw in overridden method to disallow
+ */
+ protected Query getRangeQuery(String field,
+ String part1,
+ String part2,
+ boolean startInclusive,
+ boolean endInclusive) throws ParseException
+ {
+ if (startInclusive & endInclusive) {
+ // Use the old method for the time being while it's still apart of the API
+ return getRangeQuery(field, part1, part2, true);
+ }
+
+ if ((startInclusive ^ endInclusive) && useOldRangeQuery) {
+ throw new ParseException("Cannot mix inclusive/exclusive on range query"
+ + " with useOldRangeQuery=true");
+ }
+
+ if (lowercaseExpandedTerms) {
+ part1 = part1.toLowerCase();
+ part2 = part2.toLowerCase();
+ }
+ try {
+ DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
+ df.setLenient(true);
+ Date d1 = df.parse(part1);
+ Date d2 = df.parse(part2);
+ if (endInclusive) {
+ // The user can only specify the date, not the time, so make sure
+ // the time is set to the latest possible time of that date to really
+ // include all documents:
+ Calendar cal = Calendar.getInstance(locale);
+ cal.setTime(d2);
+ cal.set(Calendar.HOUR_OF_DAY, 23);
+ cal.set(Calendar.MINUTE, 59);
+ cal.set(Calendar.SECOND, 59);
+ cal.set(Calendar.MILLISECOND, 999);
+ d2 = cal.getTime();
+ }
+ DateTools.Resolution resolution = getDateResolution(field);
+ if (resolution == null) {
+ // no default or field specific date resolution has been set,
+ // use deprecated DateField to maintain compatibilty with
+ // pre-1.9 Lucene versions.
+ part1 = DateField.dateToString(d1);
+ part2 = DateField.dateToString(d2);
+ } else {
+ part1 = DateTools.dateToString(d1, resolution);
+ part2 = DateTools.dateToString(d2, resolution);
+ }
+ }
+ catch (Exception e) { }
+
+ if(useOldRangeQuery)
+ {
+ return new RangeQuery(new Term(field, part1),
+ new Term(field, part2),
+ startInclusive & endInclusive);
+ }
+ else
+ {
+ return new ConstantScoreRangeQuery(field,part1,part2,startInclusive,endInclusive);
+ }
+ }
+
+ /**
* Factory method for generating query, given a set of clauses.
* By default creates a boolean query composed of clauses passed in.
*
@@ -873,7 +943,7 @@
| <#_WHITESPACE: ( " " | "\t" | "\n" | "\r") >
}
- SKIP : {
+ SKIP : {
< <_WHITESPACE>>
}
@@ -893,26 +963,20 @@
| )+ ( "." (<_NUM_CHAR>)+ )? )? >
| (<_TERM_CHAR>)* "*" ) >
| | [ "*", "?" ]) (<_TERM_CHAR> | ( [ "*", "?" ] ))* >
-| : RangeIn
-| : RangeEx
+| : Range
+| : Range
}
TOKEN : {
)+ ( "." (<_NUM_CHAR>)+ )? > : DEFAULT
}
- TOKEN : {
-
+ TOKEN : {
+
| : DEFAULT
-|
-|
-}
-
- TOKEN : {
-
| : DEFAULT
-|
-|
+|
+|
}
// * Query ::= ( Clause )*
@@ -1011,7 +1075,7 @@
Query Term(String field) : {
- Token term, boost=null, fuzzySlop=null, goop1, goop2;
+ Token term, boost=null, fuzzySlop=null, goop1, goop2, goop3;
boolean prefix = false;
boolean wildcard = false;
boolean fuzzy = false;
@@ -1050,32 +1114,41 @@
q = getFieldQuery(field, termImage);
}
}
- | ( ( goop1=|goop1= )
- [ ] ( goop2=|goop2= )
- )
+ | ( ( goop1=|goop1= )
+ [ ] ( goop2=|goop2= )
+ ( goop3=|goop3= ) )
[ boost= ]
{
- if (goop1.kind == RANGEIN_QUOTED) {
+ if (goop1.kind == RANGE_QUOTED) {
goop1.image = goop1.image.substring(1, goop1.image.length()-1);
}
- if (goop2.kind == RANGEIN_QUOTED) {
+ if (goop2.kind == RANGE_QUOTED) {
goop2.image = goop2.image.substring(1, goop2.image.length()-1);
}
- q = getRangeQuery(field, discardEscapeChar(goop1.image), discardEscapeChar(goop2.image), true);
+
+ if (goop3.kind == RANGEEX_END) {
+ q = getRangeQuery(field, discardEscapeChar(goop1.image), discardEscapeChar(goop2.image), true, false);
+ } else {
+ q = getRangeQuery(field, discardEscapeChar(goop1.image), discardEscapeChar(goop2.image), true, true);
+ }
}
- | ( ( goop1=|goop1= )
- [ ] ( goop2=|goop2= )
- )
+ | ( ( goop1=|goop1= )
+ [ ] ( goop2=|goop2= )
+ ( goop3=|goop3= ) )
[ boost= ]
{
- if (goop1.kind == RANGEEX_QUOTED) {
+ if (goop1.kind == RANGE_QUOTED) {
goop1.image = goop1.image.substring(1, goop1.image.length()-1);
}
- if (goop2.kind == RANGEEX_QUOTED) {
+ if (goop2.kind == RANGE_QUOTED) {
goop2.image = goop2.image.substring(1, goop2.image.length()-1);
}
- q = getRangeQuery(field, discardEscapeChar(goop1.image), discardEscapeChar(goop2.image), false);
+ if (goop3.kind == RANGEIN_END) {
+ q = getRangeQuery(field, discardEscapeChar(goop1.image), discardEscapeChar(goop2.image), false, true);
+ } else {
+ q = getRangeQuery(field, discardEscapeChar(goop1.image), discardEscapeChar(goop2.image), false, false);
+ }
}
| term=
[ fuzzySlop= ]
Index: src/java/org/apache/lucene/queryParser/QueryParserConstants.java
===================================================================
--- src/java/org/apache/lucene/queryParser/QueryParserConstants.java (revision 574284)
+++ src/java/org/apache/lucene/queryParser/QueryParserConstants.java (working copy)
@@ -27,19 +27,15 @@
int RANGEIN_START = 22;
int RANGEEX_START = 23;
int NUMBER = 24;
- int RANGEIN_TO = 25;
+ int RANGE_TO = 25;
int RANGEIN_END = 26;
- int RANGEIN_QUOTED = 27;
- int RANGEIN_GOOP = 28;
- int RANGEEX_TO = 29;
- int RANGEEX_END = 30;
- int RANGEEX_QUOTED = 31;
- int RANGEEX_GOOP = 32;
+ int RANGEEX_END = 27;
+ int RANGE_QUOTED = 28;
+ int RANGE_GOOP = 29;
int Boost = 0;
- int RangeEx = 1;
- int RangeIn = 2;
- int DEFAULT = 3;
+ int Range = 1;
+ int DEFAULT = 2;
String[] tokenImage = {
"",
@@ -69,12 +65,9 @@
"",
"\"TO\"",
"\"]\"",
- "",
- "",
- "\"TO\"",
"\"}\"",
- "",
- "",
+ "",
+ "",
};
}
Index: src/java/org/apache/lucene/queryParser/QueryParserTokenManager.java
===================================================================
--- src/java/org/apache/lucene/queryParser/QueryParserTokenManager.java (revision 574284)
+++ src/java/org/apache/lucene/queryParser/QueryParserTokenManager.java (working copy)
@@ -14,7 +14,7 @@
{
public java.io.PrintStream debugStream = System.out;
public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
-private final int jjStopStringLiteralDfa_3(int pos, long active0)
+private final int jjStopStringLiteralDfa_2(int pos, long active0)
{
switch (pos)
{
@@ -22,9 +22,9 @@
return -1;
}
}
-private final int jjStartNfa_3(int pos, long active0)
+private final int jjStartNfa_2(int pos, long active0)
{
- return jjMoveNfa_3(jjStopStringLiteralDfa_3(pos, active0), pos + 1);
+ return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1);
}
private final int jjStopAtPos(int pos, int kind)
{
@@ -32,15 +32,15 @@
jjmatchedPos = pos;
return pos + 1;
}
-private final int jjStartNfaWithStates_3(int pos, int kind, int state)
+private final int jjStartNfaWithStates_2(int pos, int kind, int state)
{
jjmatchedKind = kind;
jjmatchedPos = pos;
try { curChar = input_stream.readChar(); }
catch(java.io.IOException e) { return pos + 1; }
- return jjMoveNfa_3(state, pos + 1);
+ return jjMoveNfa_2(state, pos + 1);
}
-private final int jjMoveStringLiteralDfa0_3()
+private final int jjMoveStringLiteralDfa0_2()
{
switch(curChar)
{
@@ -49,7 +49,7 @@
case 41:
return jjStopAtPos(0, 13);
case 42:
- return jjStartNfaWithStates_3(0, 15, 36);
+ return jjStartNfaWithStates_2(0, 15, 36);
case 43:
return jjStopAtPos(0, 10);
case 45:
@@ -63,7 +63,7 @@
case 123:
return jjStopAtPos(0, 23);
default :
- return jjMoveNfa_3(0, 0);
+ return jjMoveNfa_2(0, 0);
}
}
private final void jjCheckNAdd(int state)
@@ -102,7 +102,7 @@
static final long[] jjbitVec2 = {
0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
};
-private final int jjMoveNfa_3(int startState, int curPos)
+private final int jjMoveNfa_2(int startState, int curPos)
{
int[] nextStates;
int startsAt = 0;
@@ -502,190 +502,6 @@
catch(java.io.IOException e) { return curPos; }
}
}
-private final int jjStopStringLiteralDfa_1(int pos, long active0)
-{
- switch (pos)
- {
- case 0:
- if ((active0 & 0x20000000L) != 0L)
- {
- jjmatchedKind = 32;
- return 6;
- }
- return -1;
- default :
- return -1;
- }
-}
-private final int jjStartNfa_1(int pos, long active0)
-{
- return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1);
-}
-private final int jjStartNfaWithStates_1(int pos, int kind, int state)
-{
- jjmatchedKind = kind;
- jjmatchedPos = pos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return pos + 1; }
- return jjMoveNfa_1(state, pos + 1);
-}
-private final int jjMoveStringLiteralDfa0_1()
-{
- switch(curChar)
- {
- case 84:
- return jjMoveStringLiteralDfa1_1(0x20000000L);
- case 125:
- return jjStopAtPos(0, 30);
- default :
- return jjMoveNfa_1(0, 0);
- }
-}
-private final int jjMoveStringLiteralDfa1_1(long active0)
-{
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) {
- jjStopStringLiteralDfa_1(0, active0);
- return 1;
- }
- switch(curChar)
- {
- case 79:
- if ((active0 & 0x20000000L) != 0L)
- return jjStartNfaWithStates_1(1, 29, 6);
- break;
- default :
- break;
- }
- return jjStartNfa_1(0, active0);
-}
-private final int jjMoveNfa_1(int startState, int curPos)
-{
- int[] nextStates;
- int startsAt = 0;
- jjnewStateCnt = 7;
- int i = 1;
- jjstateSet[0] = startState;
- int j, kind = 0x7fffffff;
- for (;;)
- {
- if (++jjround == 0x7fffffff)
- ReInitRounds();
- if (curChar < 64)
- {
- long l = 1L << curChar;
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- if ((0xfffffffeffffffffL & l) != 0L)
- {
- if (kind > 32)
- kind = 32;
- jjCheckNAdd(6);
- }
- if ((0x100002600L & l) != 0L)
- {
- if (kind > 6)
- kind = 6;
- }
- else if (curChar == 34)
- jjCheckNAddTwoStates(2, 4);
- break;
- case 1:
- if (curChar == 34)
- jjCheckNAddTwoStates(2, 4);
- break;
- case 2:
- if ((0xfffffffbffffffffL & l) != 0L)
- jjCheckNAddStates(16, 18);
- break;
- case 3:
- if (curChar == 34)
- jjCheckNAddStates(16, 18);
- break;
- case 5:
- if (curChar == 34 && kind > 31)
- kind = 31;
- break;
- case 6:
- if ((0xfffffffeffffffffL & l) == 0L)
- break;
- if (kind > 32)
- kind = 32;
- jjCheckNAdd(6);
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else if (curChar < 128)
- {
- long l = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- case 6:
- if ((0xdfffffffffffffffL & l) == 0L)
- break;
- if (kind > 32)
- kind = 32;
- jjCheckNAdd(6);
- break;
- case 2:
- jjAddStates(16, 18);
- break;
- case 4:
- if (curChar == 92)
- jjstateSet[jjnewStateCnt++] = 3;
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- else
- {
- int hiByte = (int)(curChar >> 8);
- int i1 = hiByte >> 6;
- long l1 = 1L << (hiByte & 077);
- int i2 = (curChar & 0xff) >> 6;
- long l2 = 1L << (curChar & 077);
- MatchLoop: do
- {
- switch(jjstateSet[--i])
- {
- case 0:
- case 6:
- if (!jjCanMove_0(hiByte, i1, i2, l1, l2))
- break;
- if (kind > 32)
- kind = 32;
- jjCheckNAdd(6);
- break;
- case 2:
- if (jjCanMove_0(hiByte, i1, i2, l1, l2))
- jjAddStates(16, 18);
- break;
- default : break;
- }
- } while(i != startsAt);
- }
- if (kind != 0x7fffffff)
- {
- jjmatchedKind = kind;
- jjmatchedPos = curPos;
- kind = 0x7fffffff;
- }
- ++curPos;
- if ((i = jjnewStateCnt) == (startsAt = 7 - (jjnewStateCnt = startsAt)))
- return curPos;
- try { curChar = input_stream.readChar(); }
- catch(java.io.IOException e) { return curPos; }
- }
-}
private final int jjMoveStringLiteralDfa0_0()
{
return jjMoveNfa_0(0, 0);
@@ -714,7 +530,7 @@
break;
if (kind > 24)
kind = 24;
- jjAddStates(19, 20);
+ jjAddStates(16, 17);
break;
case 1:
if (curChar == 46)
@@ -770,14 +586,14 @@
catch(java.io.IOException e) { return curPos; }
}
}
-private final int jjStopStringLiteralDfa_2(int pos, long active0)
+private final int jjStopStringLiteralDfa_1(int pos, long active0)
{
switch (pos)
{
case 0:
if ((active0 & 0x2000000L) != 0L)
{
- jjmatchedKind = 28;
+ jjmatchedKind = 29;
return 6;
}
return -1;
@@ -785,49 +601,51 @@
return -1;
}
}
-private final int jjStartNfa_2(int pos, long active0)
+private final int jjStartNfa_1(int pos, long active0)
{
- return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1);
+ return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1);
}
-private final int jjStartNfaWithStates_2(int pos, int kind, int state)
+private final int jjStartNfaWithStates_1(int pos, int kind, int state)
{
jjmatchedKind = kind;
jjmatchedPos = pos;
try { curChar = input_stream.readChar(); }
catch(java.io.IOException e) { return pos + 1; }
- return jjMoveNfa_2(state, pos + 1);
+ return jjMoveNfa_1(state, pos + 1);
}
-private final int jjMoveStringLiteralDfa0_2()
+private final int jjMoveStringLiteralDfa0_1()
{
switch(curChar)
{
case 84:
- return jjMoveStringLiteralDfa1_2(0x2000000L);
+ return jjMoveStringLiteralDfa1_1(0x2000000L);
case 93:
return jjStopAtPos(0, 26);
+ case 125:
+ return jjStopAtPos(0, 27);
default :
- return jjMoveNfa_2(0, 0);
+ return jjMoveNfa_1(0, 0);
}
}
-private final int jjMoveStringLiteralDfa1_2(long active0)
+private final int jjMoveStringLiteralDfa1_1(long active0)
{
try { curChar = input_stream.readChar(); }
catch(java.io.IOException e) {
- jjStopStringLiteralDfa_2(0, active0);
+ jjStopStringLiteralDfa_1(0, active0);
return 1;
}
switch(curChar)
{
case 79:
if ((active0 & 0x2000000L) != 0L)
- return jjStartNfaWithStates_2(1, 25, 6);
+ return jjStartNfaWithStates_1(1, 25, 6);
break;
default :
break;
}
- return jjStartNfa_2(0, active0);
+ return jjStartNfa_1(0, active0);
}
-private final int jjMoveNfa_2(int startState, int curPos)
+private final int jjMoveNfa_1(int startState, int curPos)
{
int[] nextStates;
int startsAt = 0;
@@ -849,8 +667,8 @@
case 0:
if ((0xfffffffeffffffffL & l) != 0L)
{
- if (kind > 28)
- kind = 28;
+ if (kind > 29)
+ kind = 29;
jjCheckNAdd(6);
}
if ((0x100002600L & l) != 0L)
@@ -867,21 +685,21 @@
break;
case 2:
if ((0xfffffffbffffffffL & l) != 0L)
- jjCheckNAddStates(16, 18);
+ jjCheckNAddStates(18, 20);
break;
case 3:
if (curChar == 34)
- jjCheckNAddStates(16, 18);
+ jjCheckNAddStates(18, 20);
break;
case 5:
- if (curChar == 34 && kind > 27)
- kind = 27;
+ if (curChar == 34 && kind > 28)
+ kind = 28;
break;
case 6:
if ((0xfffffffeffffffffL & l) == 0L)
break;
- if (kind > 28)
- kind = 28;
+ if (kind > 29)
+ kind = 29;
jjCheckNAdd(6);
break;
default : break;
@@ -897,14 +715,14 @@
{
case 0:
case 6:
- if ((0xffffffffdfffffffL & l) == 0L)
+ if ((0xdfffffffdfffffffL & l) == 0L)
break;
- if (kind > 28)
- kind = 28;
+ if (kind > 29)
+ kind = 29;
jjCheckNAdd(6);
break;
case 2:
- jjAddStates(16, 18);
+ jjAddStates(18, 20);
break;
case 4:
if (curChar == 92)
@@ -929,13 +747,13 @@
case 6:
if (!jjCanMove_0(hiByte, i1, i2, l1, l2))
break;
- if (kind > 28)
- kind = 28;
+ if (kind > 29)
+ kind = 29;
jjCheckNAdd(6);
break;
case 2:
if (jjCanMove_0(hiByte, i1, i2, l1, l2))
- jjAddStates(16, 18);
+ jjAddStates(18, 20);
break;
default : break;
}
@@ -955,8 +773,8 @@
}
}
static final int[] jjnextStates = {
- 29, 32, 23, 33, 30, 15, 17, 18, 20, 21, 32, 23, 33, 31, 34, 27,
- 2, 4, 5, 0, 1,
+ 29, 32, 23, 33, 30, 15, 17, 18, 20, 21, 32, 23, 33, 31, 34, 27,
+ 0, 1, 2, 4, 5,
};
private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2)
{
@@ -964,42 +782,39 @@
{
case 0:
return ((jjbitVec2[i2] & l2) != 0L);
- default :
+ default :
if ((jjbitVec0[i1] & l1) != 0L)
return true;
return false;
}
}
public static final String[] jjstrLiteralImages = {
-"", null, null, null, null, null, null, null, null, null, "\53", "\55", "\50",
-"\51", "\72", "\52", "\136", null, null, null, null, null, "\133", "\173", null,
-"\124\117", "\135", null, null, "\124\117", "\175", null, null, };
+"", null, null, null, null, null, null, null, null, null, "\53", "\55", "\50",
+"\51", "\72", "\52", "\136", null, null, null, null, null, "\133", "\173", null,
+"\124\117", "\135", "\175", null, null, };
public static final String[] lexStateNames = {
- "Boost",
- "RangeEx",
- "RangeIn",
- "DEFAULT",
+ "Boost",
+ "Range",
+ "DEFAULT",
};
public static final int[] jjnewLexState = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, 2, 1, 3,
- -1, 3, -1, -1, -1, 3, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, 1, 1, 2,
+ -1, 2, 2, -1, -1,
};
static final long[] jjtoToken = {
- 0x1ffffff81L,
+ 0x3fffff81L,
};
static final long[] jjtoSkip = {
- 0x40L,
+ 0x40L,
};
protected CharStream input_stream;
private final int[] jjrounds = new int[36];
private final int[] jjstateSet = new int[72];
protected char curChar;
-public QueryParserTokenManager(CharStream stream)
-{
+public QueryParserTokenManager(CharStream stream){
input_stream = stream;
}
-public QueryParserTokenManager(CharStream stream, int lexState)
-{
+public QueryParserTokenManager(CharStream stream, int lexState){
this(stream);
SwitchTo(lexState);
}
@@ -1024,7 +839,7 @@
}
public void SwitchTo(int lexState)
{
- if (lexState >= 4 || lexState < 0)
+ if (lexState >= 3 || lexState < 0)
throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
else
curLexState = lexState;
@@ -1043,14 +858,14 @@
return t;
}
-int curLexState = 3;
-int defaultLexState = 3;
+int curLexState = 2;
+int defaultLexState = 2;
int jjnewStateCnt;
int jjround;
int jjmatchedPos;
int jjmatchedKind;
-public Token getNextToken()
+public Token getNextToken()
{
int kind;
Token specialToken = null;
@@ -1059,13 +874,13 @@
EOFLoop :
for (;;)
- {
- try
- {
+ {
+ try
+ {
curChar = input_stream.BeginToken();
- }
+ }
catch(java.io.IOException e)
- {
+ {
jjmatchedKind = 0;
matchedToken = jjFillToken();
return matchedToken;
@@ -1088,11 +903,6 @@
jjmatchedPos = 0;
curPos = jjMoveStringLiteralDfa0_2();
break;
- case 3:
- jjmatchedKind = 0x7fffffff;
- jjmatchedPos = 0;
- curPos = jjMoveStringLiteralDfa0_3();
- break;
}
if (jjmatchedKind != 0x7fffffff)
{
Index: src/site/src/documentation/content/xdocs/queryparsersyntax.xml
===================================================================
--- src/site/src/documentation/content/xdocs/queryparsersyntax.xml (revision 574284)
+++ src/site/src/documentation/content/xdocs/queryparsersyntax.xml (working copy)
@@ -129,8 +129,11 @@
This will find documents whose mod_date fields have values between 20020101 and 20030101, inclusive.
Note that Range Queries are not reserved for date fields. You could also use range queries with non-date fields:
title:{Aida TO Carmen}
-
This will find all documents whose titles are between Aida and Carmen, but not including Aida and Carmen.
-
Inclusive range queries are denoted by square brackets. Exclusive range queries are denoted by
+
This will find all documents whose titles are between Aida and Carmen, but not including Aida and Carmen.
+ Note that Range Queries need not be solely inclusive or exclusive:
+ firstName:[Bob TO Mike}
+
This will find all documents whose firstName fields have values between Bob and Mike, including Bob but not Mike.
+
Inclusive range query bounds are denoted by square brackets. Exclusive range query bounds are denoted by
curly brackets.
Index: src/test/org/apache/lucene/queryParser/TestQueryParser.java
===================================================================
--- src/test/org/apache/lucene/queryParser/TestQueryParser.java (revision 574284)
+++ src/test/org/apache/lucene/queryParser/TestQueryParser.java (working copy)
@@ -128,6 +128,16 @@
+ "/, expecting /" + result + "/");
}
}
+
+ public void assertQueryNotEquals(String query1, String query2, Analyzer a)
+ throws Exception {
+ Query q1 = getQuery(query1, a);
+ Query q2 = getQuery(query2, a);
+ if (q1.equals(q2)) {
+ fail("Query /" + query1 + "/ is equal to /" + query2
+ + "/, expected not equal");
+ }
+ }
public void assertQueryEquals(QueryParser qp, String field, String query, String result)
throws Exception {
@@ -409,6 +419,55 @@
assertQueryEquals("[ a TO z] AND bar", null, "+[a TO z] +bar");
assertQueryEquals("( bar blar { a TO z}) ", null, "bar blar {a TO z}");
assertQueryEquals("gack ( bar blar { a TO z}) ", null, "gack (bar blar {a TO z})");
+
+ try {
+ qp.parse("[a TO z}");
+ fail();
+ } catch (ParseException e) {
+ // Expected exception
+ }
+ try {
+ qp.parse("{a TO z]");
+ fail();
+ } catch (ParseException e) {
+ // Expected exception
+ }
+
+ qp.setUseOldRangeQuery(false);
+ try {
+ qp.parse("[a TO z}");
+ } catch (ParseException e) {
+ fail();
+ }
+ try {
+ qp.parse("{a TO z]");
+ } catch (ParseException e) {
+ fail();
+ }
+
+ assertQueryNotEquals("[a TO z}", "{a TO z]", null);
+ assertQueryNotEquals("[a TO z}", "{a TO z}", null);
+ assertQueryNotEquals("{a TO z]", "[a TO z}", null);
+ assertQueryNotEquals("{a TO z]", "[a TO z]", null);
+ assertQueryNotEquals("[a TO z]", "{a TO z}", null);
+ assertQueryNotEquals("[a TO z]", "{a TO z]", null);
+ assertQueryNotEquals("[a TO z]", "[a TO z}", null);
+ assertQueryNotEquals("{a TO z}", "[a TO z}", null);
+ assertQueryNotEquals("{a TO z}", "{a TO z]", null);
+
+ assertQueryEquals("[ a TO z }", null, "[a TO z}");
+ assertQueryEquals("{ a TO z ]", null, "{a TO z]");
+ assertQueryEquals("[ a TO z}", null, "[a TO z}");
+ assertQueryEquals("{ a TO z]", null, "{a TO z]");
+ assertQueryEquals("[ a TO z }^2.0", null, "[a TO z}^2.0");
+ assertQueryEquals("[ a TO z} OR bar", null, "[a TO z} bar");
+ assertQueryEquals("{ a TO z] OR bar", null, "{a TO z] bar");
+ assertQueryEquals("[ a TO z} AND bar", null, "+[a TO z} +bar");
+ assertQueryEquals("{ a TO z] AND bar", null, "+{a TO z] +bar");
+ assertQueryEquals("( bar blar [ a TO z}) ", null, "bar blar [a TO z}");
+ assertQueryEquals("( bar blar { a TO z]) ", null, "bar blar {a TO z]");
+ assertQueryEquals("gack ( bar blar [ a TO z}) ", null, "gack (bar blar [a TO z})");
+ assertQueryEquals("gack ( bar blar { a TO z]) ", null, "gack (bar blar {a TO z])");
}
/** for testing legacy DateField support */