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:
Doron Cohen 2007-06-26 00:40:20 +00:00
parent 7505950c5f
commit 1d77b82dbf
6 changed files with 93 additions and 17 deletions

View File

@ -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

View File

@ -208,7 +208,10 @@ public class MultiFieldQueryParser extends QueryParser
{
QueryParser qp = new QueryParser(fields[i], analyzer);
Query q = qp.parse(queries[i]);
bQuery.add(q, BooleanClause.Occur.SHOULD);
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,7 +254,10 @@ 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);
bQuery.add(q, flags[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;
}
@ -297,7 +303,10 @@ public class MultiFieldQueryParser extends QueryParser
{
QueryParser qp = new QueryParser(fields[i], analyzer);
Query q = qp.parse(queries[i]);
bQuery.add(q, flags[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;
}

View File

@ -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,9 +615,12 @@ 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));
query.add((BooleanClause)clauses.elementAt(i));
}
return query;
}
@ -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;

View File

@ -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,9 +639,12 @@ 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));
query.add((BooleanClause)clauses.elementAt(i));
}
return query;
}

View File

@ -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 {

View File

@ -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);
}