You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by rm...@apache.org on 2011/02/11 23:51:53 UTC

svn commit: r1069977 - in /lucene/dev/trunk/lucene: CHANGES.txt src/java/org/apache/lucene/queryParser/QueryParserBase.java src/test/org/apache/lucene/queryParser/TestQueryParser.java

Author: rmuir
Date: Fri Feb 11 22:51:53 2011
New Revision: 1069977

URL: http://svn.apache.org/viewvc?rev=1069977&view=rev
Log:
LUCENE-2892: Add QueryParser.newFieldQuery

Modified:
    lucene/dev/trunk/lucene/CHANGES.txt
    lucene/dev/trunk/lucene/src/java/org/apache/lucene/queryParser/QueryParserBase.java
    lucene/dev/trunk/lucene/src/test/org/apache/lucene/queryParser/TestQueryParser.java

Modified: lucene/dev/trunk/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/CHANGES.txt?rev=1069977&r1=1069976&r2=1069977&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/CHANGES.txt (original)
+++ lucene/dev/trunk/lucene/CHANGES.txt Fri Feb 11 22:51:53 2011
@@ -195,6 +195,10 @@ API Changes
   for building top-level norms. If you really need a top-level norms, use 
   MultiNorms or SlowMultiReaderWrapper. (Robert Muir, Mike Mccandless)
 
+* LUCENE-2892: Add QueryParser.newFieldQuery (called by getFieldQuery by default)
+  which takes Analyzer as a parameter, for easier customization by subclasses.
+  (Robert Muir)
+
 New features
 
 * LUCENE-2604: Added RegexpQuery support to QueryParser. Regular expressions

Modified: lucene/dev/trunk/lucene/src/java/org/apache/lucene/queryParser/QueryParserBase.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/src/java/org/apache/lucene/queryParser/QueryParserBase.java?rev=1069977&r1=1069976&r2=1069977&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/src/java/org/apache/lucene/queryParser/QueryParserBase.java (original)
+++ lucene/dev/trunk/lucene/src/java/org/apache/lucene/queryParser/QueryParserBase.java Fri Feb 11 22:51:53 2011
@@ -467,7 +467,14 @@ public abstract class QueryParserBase {
   /**
    * @exception org.apache.lucene.queryParser.ParseException throw in overridden method to disallow
    */
-  protected Query getFieldQuery(String field, String queryText, boolean quoted)  throws ParseException {
+  protected Query getFieldQuery(String field, String queryText, boolean quoted) throws ParseException {
+    return newFieldQuery(analyzer, field, queryText, quoted);
+  }
+  
+  /**
+   * @exception org.apache.lucene.queryParser.ParseException throw in overridden method to disallow
+   */
+  protected Query newFieldQuery(Analyzer analyzer, String field, String queryText, boolean quoted)  throws ParseException {
     // Use the analyzer to get all the tokens, and then build a TermQuery,
     // PhraseQuery, or nothing based on the term count
 

Modified: lucene/dev/trunk/lucene/src/test/org/apache/lucene/queryParser/TestQueryParser.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/src/test/org/apache/lucene/queryParser/TestQueryParser.java?rev=1069977&r1=1069976&r2=1069977&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/src/test/org/apache/lucene/queryParser/TestQueryParser.java (original)
+++ lucene/dev/trunk/lucene/src/test/org/apache/lucene/queryParser/TestQueryParser.java Fri Feb 11 22:51:53 2011
@@ -35,6 +35,7 @@ import org.apache.lucene.analysis.TokenS
 import org.apache.lucene.analysis.Tokenizer;
 import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
+import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
 import org.apache.lucene.document.DateTools;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
@@ -58,6 +59,7 @@ import org.apache.lucene.search.Wildcard
 import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util.Version;
 import org.apache.lucene.util.automaton.BasicAutomata;
 import org.apache.lucene.util.automaton.CharacterRunAutomaton;
 import org.apache.lucene.util.automaton.RegExp;
@@ -1175,5 +1177,87 @@ public class TestQueryParser extends Luc
       // expected
     }
   }
+  
+  /**
+   * adds synonym of "dog" for "dogs".
+   */
+  private class MockSynonymFilter extends TokenFilter {
+    CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
+    PositionIncrementAttribute posIncAtt = addAttribute(PositionIncrementAttribute.class);
+    boolean addSynonym = false;
+    
+    public MockSynonymFilter(TokenStream input) {
+      super(input);
+    }
+
+    @Override
+    public final boolean incrementToken() throws IOException {
+      if (addSynonym) { // inject our synonym
+        clearAttributes();
+        termAtt.setEmpty().append("dog");
+        posIncAtt.setPositionIncrement(0);
+        addSynonym = false;
+        return true;
+      }
+      
+      if (input.incrementToken()) {
+        addSynonym = termAtt.toString().equals("dogs");
+        return true;
+      } else {
+        return false;
+      }
+    } 
+  }
+  
+  /** whitespace+lowercase analyzer with synonyms */
+  private class Analyzer1 extends Analyzer {
+    @Override
+    public TokenStream tokenStream(String fieldName, Reader reader) {
+      return new MockSynonymFilter(new MockTokenizer(reader, MockTokenizer.WHITESPACE, true));
+    }
+  }
+  
+  /** whitespace+lowercase analyzer without synonyms */
+  private class Analyzer2 extends Analyzer {
+    @Override
+    public TokenStream tokenStream(String fieldName, Reader reader) {
+      return new MockTokenizer(reader, MockTokenizer.WHITESPACE, true);
+    }
+  }
+  
+  /** query parser that doesn't expand synonyms when users use double quotes */
+  private class SmartQueryParser extends QueryParser {
+    Analyzer morePrecise = new Analyzer2();
+    
+    public SmartQueryParser() {
+      super(TEST_VERSION_CURRENT, "field", new Analyzer1());
+    }
 
+    @Override
+    protected Query getFieldQuery(String field, String queryText, boolean quoted)
+        throws ParseException {
+      if (quoted)
+        return newFieldQuery(morePrecise, field, queryText, quoted);
+      else
+        return super.getFieldQuery(field, queryText, quoted);
+    }
+  }
+  
+  public void testNewFieldQuery() throws Exception {
+    /** ordinary behavior, synonyms form uncoordinated boolean query */
+    QueryParser dumb = new QueryParser(TEST_VERSION_CURRENT, "field", new Analyzer1());
+    BooleanQuery expanded = new BooleanQuery(true);
+    expanded.add(new TermQuery(new Term("field", "dogs")), BooleanClause.Occur.SHOULD);
+    expanded.add(new TermQuery(new Term("field", "dog")), BooleanClause.Occur.SHOULD);
+    assertEquals(expanded, dumb.parse("\"dogs\""));
+    /** even with the phrase operator the behavior is the same */
+    assertEquals(expanded, dumb.parse("dogs"));
+    
+    /** custom behavior, the synonyms are expanded, unless you use quote operator */
+    QueryParser smart = new SmartQueryParser();
+    assertEquals(expanded, smart.parse("dogs"));
+    
+    Query unexpanded = new TermQuery(new Term("field", "dogs"));
+    assertEquals(unexpanded, smart.parse("\"dogs\""));
+  }
 }