Peter's problem intrigued me, so I wrote my own test case using two simple
Filters that filter out all but the first (or last) doc.  I seem to be
getting the same results he is, which is certianly.  see attached test case.

while this definitely seems like a bug, it also seems like a fairly
inefficinent way of approaching hte problem in general, instead of:
  BooleanQuery containing:
    a) FilteredQuery wrapping:
        Query for "all" -- filtered by -- RangeFilter #1
    b) FilteredQuery wrapping:
        Query for "all" -- filtered by -- RangeFilter #2

...it seems like it would make more sense to use...

  FilterQuery wrapping:
    Query for all -- filtered by -- ChainedFilter containing:
      a) RangeFilter #1
      b) RangeFilter #2




: Date: Fri, 1 Apr 2005 13:29:04 -0500
: From: Erik Hatcher <[EMAIL PROTECTED]>
: Reply-To: java-user@lucene.apache.org
: To: java-user@lucene.apache.org
: Subject: Re: FilteredQuery and Boolean AND
:
: Peter,
:
: Could you provide a straight-forward test case that indexes a few
: documents into a RAMDirectory and demonstrates the problem you're
: having with AND'd FilteredQuery's?
:
: Give me something concrete and simple and I'll dig into it further.
:
:       Erik
:
: On Apr 1, 2005, at 11:13 AM, Kipping, Peter wrote:
:
: > Any ideas on this?  I have purchased your book, Lucene in Action, which
: > is quite good.  To make things easier, consider the example on p212.
: > In
: > item 4, when you combine the queries, what happens you combine them in
: > and AND fashion?  The book only has OR, which works.  Although it may
: > work since the book only has one filtered query, but what if you made
: > them both filtered queries and ANDed them?
: >
: > Thanks,
: > Peter
: >
: > -----Original Message-----
: > From: Kipping, Peter [mailto:[EMAIL PROTECTED]
: > Sent: Friday, March 25, 2005 10:34 AM
: > To: java-user@lucene.apache.org
: > Subject: FilteredQuery and Boolean AND
: >
: > I have the following query structure:
: >
: > BooleanQuery q2 = new BooleanQuery();
: > TermQuery tq = new TermQuery(new Term("all_entries", "y"));
: > FilteredQuery fq = new FilteredQuery(tq, ft);
: > FilteredQuery fq2 = new FilteredQuery(tq, ft2);
: > q2.add(fq, false, false);
: > q2.add(fq2, false, false);
: >
: > The two filters are searches over numeric ranges.  I'm using filters so
: > I don't get the TooManyBooleanClauses Exception.  And my TermQuery tq
: > is
: > just a field that has 'y' in every document so I can filter over the
: > entire index.  The last two lines I am creating a boolean OR, and
: > everything works fine.  I get back 30 documents which is correct.
: >
: > However when I change the last two lines to create an AND:
: >
: > q2.add(fq, true, false);
: > q2.add(fq2, true, false);
: >
: > I still get back 30 documents, which is not correct.  It should be 0.
: > What's going on with FilteredQuery?
: >
: > Thanks,
: > Peter
: >
: >
: > ---------------------------------------------------------------------
: > To unsubscribe, e-mail: [EMAIL PROTECTED]
: > For additional commands, e-mail: [EMAIL PROTECTED]
: >
: >
: >
: >
: > ---------------------------------------------------------------------
: > To unsubscribe, e-mail: [EMAIL PROTECTED]
: > For additional commands, e-mail: [EMAIL PROTECTED]
:
:
: ---------------------------------------------------------------------
: To unsubscribe, e-mail: [EMAIL PROTECTED]
: For additional commands, e-mail: [EMAIL PROTECTED]
:



-Hoss
import org.apache.lucene.index.Term;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.analysis.SimpleAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.DateField;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.FilteredQuery;

import java.io.IOException;
import java.util.Random;
import java.util.BitSet;

import junit.framework.TestCase;

public class TestKippingPeterBug extends TestCase {

    public static final boolean F = false;
    public static final boolean T = true;

    public static String[] data = new String [] {
        "a b   m n",
        "a x   q r",
        "a b   s t",
        "a x   e f",
        "a"
    };

    
    RAMDirectory index = new RAMDirectory();
    IndexReader r;
    IndexSearcher s;
    Query ALL = new TermQuery(new Term("data","a"));

    
    public TestKippingPeterBug(String name) {
	super(name);
    }
    public TestKippingPeterBug() {
        super();
    }

    public void setUp() throws Exception {

        /* build an index */
        IndexWriter writer = new IndexWriter(index,
                                             new SimpleAnalyzer(), T);
        
        for (int i = 0; i < data.length; i++) {
            Document doc = new Document();
            doc.add(Field.Keyword("id",String.valueOf(i)));
            doc.add(Field.Text("data",data[i]));
            writer.addDocument(doc);
        }
        
        writer.optimize();
        writer.close();

        r = IndexReader.open(index);
        s = new IndexSearcher(r);
        
    }

    public void testA() throws Exception {
        Hits result;

        result = s.search(ALL);
        assertEquals("not all docs found", data.length, result.length());

    }

    public void testFilters() throws Exception {

        Filter f = new FirstFilter();
        Filter l = new LastFilter();
        
        Hits result;
        
        assertEquals("only one should be set in FirstFilter",
                     1, f.bits(r).cardinality());
        assertEquals("only one should be set in LastFilter",
                     1, l.bits(r).cardinality());

        result = s.search(ALL, f);
        assertEquals("should get one doc from FirstFilter(ALL)",
                     1, result.length());
        assertEquals("wrong doc from FirstFilter(ALL)",
                     0, result.id(0));
                    
        result = s.search(ALL, l);
        assertEquals("should get one doc from LastFilter(ALL)",
                     1, result.length());
        assertEquals("wrong doc from LastFilter(ALL)",
                     data.length-1, result.id(0));
                    
    }

    public void testBooleanFilteredQuery() throws Exception {

        Filter f = new FirstFilter();
        Filter l = new LastFilter();

        Query ff = new FilteredQuery(ALL, f);
        Query ll = new FilteredQuery(ALL, l);
        
        Hits result;

        result = s.search(ff);
        assertEquals("should get one doc from FirstFilter(ALL)",
                     1, result.length());
        assertEquals("wrong doc from FirstFilter(ALL)",
                     0, result.id(0));
                    
        result = s.search(ll);
        assertEquals("should get one doc from LastFilter(ALL)",
                     1, result.length());
        assertEquals("wrong doc from LastFilter(ALL)",
                     data.length-1, result.id(0));


        BooleanQuery or = new BooleanQuery();
        or.add(ff, false, false);
        or.add(ll, false, false);
        
        result = s.search(or);
        assertEquals("should get two docs from *or*",
                     2, result.length());
                    
        BooleanQuery and = new BooleanQuery();
        and.add(ff, true, false);
        and.add(ll, true, false);
        
        result = s.search(and);
        assertEquals("should get no docs from *and*",
                     0, result.length());
                    
                    
    }

    
    
}

class FirstFilter extends Filter {
    /** only lets the first doc in the index pass the filter */
    public BitSet bits(IndexReader r) {
        BitSet b = new BitSet(r.maxDoc());
        b.set(0);
        return b;
    }
}
class LastFilter extends Filter {
    /** only lets the last doc in the index pass the filter */
    public BitSet bits(IndexReader r) {
        BitSet b = new BitSet(r.maxDoc());
        b.set(r.maxDoc()-1);
        return b;
    }
}

    
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to