mirror of https://github.com/apache/lucene.git
LUCENE-933: QueryParser fixed to not produce empty sub
BooleanQueries "()" even if the Analyzer proudced no tokens for input. git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@550647 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
7505950c5f
commit
1d77b82dbf
|
@ -10,6 +10,10 @@ API Changes
|
|||
|
||||
Bug fixes
|
||||
|
||||
1. LUCENE-933: QueryParser fixed to not produce empty sub
|
||||
BooleanQueries "()" even if the Analyzer proudced no
|
||||
tokens for input. (Doron Cohen)
|
||||
|
||||
New features
|
||||
|
||||
Optimizations
|
||||
|
|
|
@ -208,8 +208,11 @@ public class MultiFieldQueryParser extends QueryParser
|
|||
{
|
||||
QueryParser qp = new QueryParser(fields[i], analyzer);
|
||||
Query q = qp.parse(queries[i]);
|
||||
if (q!=null && // q never null, just being defensive
|
||||
(!(q instanceof BooleanQuery) || ((BooleanQuery)q).getClauses().length>0)) {
|
||||
bQuery.add(q, BooleanClause.Occur.SHOULD);
|
||||
}
|
||||
}
|
||||
return bQuery;
|
||||
}
|
||||
|
||||
|
@ -251,8 +254,11 @@ public class MultiFieldQueryParser extends QueryParser
|
|||
for (int i = 0; i < fields.length; i++) {
|
||||
QueryParser qp = new QueryParser(fields[i], analyzer);
|
||||
Query q = qp.parse(query);
|
||||
if (q!=null && // q never null, just being defensive
|
||||
(!(q instanceof BooleanQuery) || ((BooleanQuery)q).getClauses().length>0)) {
|
||||
bQuery.add(q, flags[i]);
|
||||
}
|
||||
}
|
||||
return bQuery;
|
||||
}
|
||||
|
||||
|
@ -297,8 +303,11 @@ public class MultiFieldQueryParser extends QueryParser
|
|||
{
|
||||
QueryParser qp = new QueryParser(fields[i], analyzer);
|
||||
Query q = qp.parse(queries[i]);
|
||||
if (q!=null && // q never null, just being defensive
|
||||
(!(q instanceof BooleanQuery) || ((BooleanQuery)q).getClauses().length>0)) {
|
||||
bQuery.add(q, flags[i]);
|
||||
}
|
||||
}
|
||||
return bQuery;
|
||||
}
|
||||
|
||||
|
|
|
@ -143,7 +143,8 @@ public class QueryParser implements QueryParserConstants {
|
|||
ReInit(new FastCharStream(new StringReader(query)));
|
||||
try {
|
||||
// TopLevelQuery is a Query followed by the end-of-input (EOF)
|
||||
return TopLevelQuery(field);
|
||||
Query res = TopLevelQuery(field);
|
||||
return res!=null ? res : new BooleanQuery();
|
||||
}
|
||||
catch (ParseException tme) {
|
||||
// rethrow to include the original query:
|
||||
|
@ -614,6 +615,9 @@ public class QueryParser implements QueryParserConstants {
|
|||
protected Query getBooleanQuery(Vector clauses, boolean disableCoord)
|
||||
throws ParseException
|
||||
{
|
||||
if (clauses.size()==0) {
|
||||
return null; // all clause words were filtered away by the analyzer.
|
||||
}
|
||||
BooleanQuery query = new BooleanQuery(disableCoord);
|
||||
for (int i = 0; i < clauses.size(); i++) {
|
||||
query.add((BooleanClause)clauses.elementAt(i));
|
||||
|
@ -1258,16 +1262,6 @@ public class QueryParser implements QueryParserConstants {
|
|||
finally { jj_save(0, xla); }
|
||||
}
|
||||
|
||||
final private boolean jj_3_1() {
|
||||
Token xsp;
|
||||
xsp = jj_scanpos;
|
||||
if (jj_3R_2()) {
|
||||
jj_scanpos = xsp;
|
||||
if (jj_3R_3()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
final private boolean jj_3R_3() {
|
||||
if (jj_scan_token(STAR)) return true;
|
||||
if (jj_scan_token(COLON)) return true;
|
||||
|
@ -1280,6 +1274,16 @@ public class QueryParser implements QueryParserConstants {
|
|||
return false;
|
||||
}
|
||||
|
||||
final private boolean jj_3_1() {
|
||||
Token xsp;
|
||||
xsp = jj_scanpos;
|
||||
if (jj_3R_2()) {
|
||||
jj_scanpos = xsp;
|
||||
if (jj_3R_3()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public QueryParserTokenManager token_source;
|
||||
public Token token, jj_nt;
|
||||
private int jj_ntk;
|
||||
|
|
|
@ -167,7 +167,8 @@ public class QueryParser {
|
|||
ReInit(new FastCharStream(new StringReader(query)));
|
||||
try {
|
||||
// TopLevelQuery is a Query followed by the end-of-input (EOF)
|
||||
return TopLevelQuery(field);
|
||||
Query res = TopLevelQuery(field);
|
||||
return res!=null ? res : new BooleanQuery();
|
||||
}
|
||||
catch (ParseException tme) {
|
||||
// rethrow to include the original query:
|
||||
|
@ -638,6 +639,9 @@ public class QueryParser {
|
|||
protected Query getBooleanQuery(Vector clauses, boolean disableCoord)
|
||||
throws ParseException
|
||||
{
|
||||
if (clauses.size()==0) {
|
||||
return null; // all clause words were filtered away by the analyzer.
|
||||
}
|
||||
BooleanQuery query = new BooleanQuery(disableCoord);
|
||||
for (int i = 0; i < clauses.size(); i++) {
|
||||
query.add((BooleanClause)clauses.elementAt(i));
|
||||
|
|
|
@ -26,9 +26,11 @@ import org.apache.lucene.document.Document;
|
|||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.index.IndexWriter;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.Hits;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.BooleanClause.Occur;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.RAMDirectory;
|
||||
|
||||
|
@ -42,6 +44,32 @@ import java.util.Map;
|
|||
*/
|
||||
public class TestMultiFieldQueryParser extends TestCase {
|
||||
|
||||
/** test stop words arsing for both the non static form, and for the
|
||||
* corresponding static form (qtxt, fields[]). */
|
||||
public void tesStopwordsParsing() throws Exception {
|
||||
assertStopQueryEquals("one", "b:one t:one");
|
||||
assertStopQueryEquals("one stop", "b:one t:one");
|
||||
assertStopQueryEquals("one (stop)", "b:one t:one");
|
||||
assertStopQueryEquals("one ((stop))", "b:one t:one");
|
||||
assertStopQueryEquals("stop", "");
|
||||
assertStopQueryEquals("(stop)", "");
|
||||
assertStopQueryEquals("((stop))", "");
|
||||
}
|
||||
|
||||
// verify parsing of query using a stopping analyzer
|
||||
private void assertStopQueryEquals (String qtxt, String expectedRes) throws Exception {
|
||||
String[] fields = {"b", "t"};
|
||||
Occur occur[] = {Occur.SHOULD, Occur.SHOULD};
|
||||
TestQueryParser.QPTestAnalyzer a = new TestQueryParser.QPTestAnalyzer();
|
||||
MultiFieldQueryParser mfqp = new MultiFieldQueryParser(fields, a);
|
||||
|
||||
Query q = mfqp.parse(qtxt);
|
||||
assertEquals(expectedRes, q.toString());
|
||||
|
||||
q = MultiFieldQueryParser.parse(qtxt, fields, occur, a);
|
||||
assertEquals(expectedRes, q.toString());
|
||||
}
|
||||
|
||||
public void testSimple() throws Exception {
|
||||
String[] fields = {"b", "t"};
|
||||
MultiFieldQueryParser mfqp = new MultiFieldQueryParser(fields, new StandardAnalyzer());
|
||||
|
@ -151,6 +179,18 @@ public class TestMultiFieldQueryParser extends TestCase {
|
|||
} catch(IllegalArgumentException e) {
|
||||
// expected exception, array length differs
|
||||
}
|
||||
|
||||
// check also with stop words for this static form (qtxts[], fields[]).
|
||||
TestQueryParser.QPTestAnalyzer stopA = new TestQueryParser.QPTestAnalyzer();
|
||||
|
||||
String[] queries6 = {"((+stop))", "+((stop))"};
|
||||
q = MultiFieldQueryParser.parse(queries6, fields, stopA);
|
||||
assertEquals("", q.toString());
|
||||
|
||||
String[] queries7 = {"one ((+stop)) +more", "+((stop)) +two"};
|
||||
q = MultiFieldQueryParser.parse(queries7, fields, stopA);
|
||||
assertEquals("(b:one +b:more) (+t:two)", q.toString());
|
||||
|
||||
}
|
||||
|
||||
public void testStaticMethod2() throws ParseException {
|
||||
|
|
|
@ -365,15 +365,30 @@ public class TestQueryParser extends TestCase {
|
|||
}
|
||||
|
||||
public void testQPA() throws Exception {
|
||||
assertQueryEquals("term term^3.0 term", qpAnalyzer, "term term^3.0 term");
|
||||
assertQueryEquals("term stop^3.0 term", qpAnalyzer, "term term");
|
||||
|
||||
assertQueryEquals("term term term", qpAnalyzer, "term term term");
|
||||
assertQueryEquals("term +stop term", qpAnalyzer, "term term");
|
||||
assertQueryEquals("term -stop term", qpAnalyzer, "term term");
|
||||
|
||||
assertQueryEquals("drop AND (stop) AND roll", qpAnalyzer, "+drop +roll");
|
||||
assertQueryEquals("term +(stop) term", qpAnalyzer, "term term");
|
||||
assertQueryEquals("term -(stop) term", qpAnalyzer, "term term");
|
||||
|
||||
assertQueryEquals("drop AND stop AND roll", qpAnalyzer, "+drop +roll");
|
||||
assertQueryEquals("term phrase term", qpAnalyzer,
|
||||
"term \"phrase1 phrase2\" term");
|
||||
assertQueryEquals("term AND NOT phrase term", qpAnalyzer,
|
||||
"+term -\"phrase1 phrase2\" term");
|
||||
assertQueryEquals("stop^3", qpAnalyzer, "");
|
||||
assertQueryEquals("stop", qpAnalyzer, "");
|
||||
assertQueryEquals("(stop)^3", qpAnalyzer, "");
|
||||
assertQueryEquals("((stop))^3", qpAnalyzer, "");
|
||||
assertQueryEquals("(stop^3)", qpAnalyzer, "");
|
||||
assertQueryEquals("((stop)^3)", qpAnalyzer, "");
|
||||
assertQueryEquals("(stop)", qpAnalyzer, "");
|
||||
assertQueryEquals("((stop))", qpAnalyzer, "");
|
||||
assertTrue(getQuery("term term term", qpAnalyzer) instanceof BooleanQuery);
|
||||
assertTrue(getQuery("term +stop", qpAnalyzer) instanceof TermQuery);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue