| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| using System; |
| using Lucene.Net.Index; |
| using Lucene.Net.Store; |
| using NUnit.Framework; |
| |
| using WhitespaceAnalyzer = Lucene.Net.Analysis.WhitespaceAnalyzer; |
| using Document = Lucene.Net.Documents.Document; |
| using Field = Lucene.Net.Documents.Field; |
| using IndexWriter = Lucene.Net.Index.IndexWriter; |
| using Term = Lucene.Net.Index.Term; |
| using ParseException = Lucene.Net.QueryParsers.ParseException; |
| using QueryParser = Lucene.Net.QueryParsers.QueryParser; |
| using RAMDirectory = Lucene.Net.Store.RAMDirectory; |
| using LuceneTestCase = Lucene.Net.Util.LuceneTestCase; |
| |
| namespace Lucene.Net.Search |
| { |
| |
| /// <summary>Test BooleanQuery2 against BooleanQuery by overriding the standard query parser. |
| /// This also tests the scoring order of BooleanQuery. |
| /// </summary> |
| [TestFixture] |
| public class TestBoolean2:LuceneTestCase |
| { |
| [Serializable] |
| private class AnonymousClassDefaultSimilarity:DefaultSimilarity |
| { |
| public AnonymousClassDefaultSimilarity(TestBoolean2 enclosingInstance) |
| { |
| InitBlock(enclosingInstance); |
| } |
| private void InitBlock(TestBoolean2 enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestBoolean2 enclosingInstance; |
| public TestBoolean2 Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| public override float Coord(int overlap, int maxOverlap) |
| { |
| return overlap / ((float) maxOverlap - 1); |
| } |
| } |
| private IndexSearcher searcher; |
| private IndexSearcher bigSearcher; |
| private IndexReader reader; |
| private static int NUM_EXTRA_DOCS = 6000; |
| |
| public const System.String field = "field"; |
| private Directory dir2; |
| private int mulFactor; |
| |
| [SetUp] |
| public override void SetUp() |
| { |
| base.SetUp(); |
| RAMDirectory directory = new RAMDirectory(); |
| IndexWriter writer = new IndexWriter(directory, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| for (int i = 0; i < docFields.Length; i++) |
| { |
| Document document = new Document(); |
| document.Add(new Field(field, docFields[i], Field.Store.NO, Field.Index.ANALYZED)); |
| writer.AddDocument(document); |
| } |
| writer.Close(); |
| searcher = new IndexSearcher(directory, true); |
| |
| // Make big index |
| dir2 = new MockRAMDirectory(directory); |
| |
| // First multiply small test index: |
| mulFactor = 1; |
| int docCount = 0; |
| do |
| { |
| Directory copy = new RAMDirectory(dir2); |
| IndexWriter indexWriter = new IndexWriter(dir2, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); |
| indexWriter.AddIndexesNoOptimize(new[] {copy}); |
| docCount = indexWriter.MaxDoc(); |
| indexWriter.Close(); |
| mulFactor *= 2; |
| } while (docCount < 3000); |
| |
| IndexWriter w = new IndexWriter(dir2, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); |
| Document doc = new Document(); |
| doc.Add(new Field("field2", "xxx", Field.Store.NO, Field.Index.ANALYZED)); |
| for (int i = 0; i < NUM_EXTRA_DOCS / 2; i++) |
| { |
| w.AddDocument(doc); |
| } |
| doc = new Document(); |
| doc.Add(new Field("field2", "big bad bug", Field.Store.NO, Field.Index.ANALYZED)); |
| for (int i = 0; i < NUM_EXTRA_DOCS / 2; i++) |
| { |
| w.AddDocument(doc); |
| } |
| // optimize to 1 segment |
| w.Optimize(); |
| reader = w.GetReader(); |
| w.Close(); |
| bigSearcher = new IndexSearcher(reader); |
| } |
| |
| [TearDown] |
| public override void TearDown() |
| { |
| reader.Close(); |
| dir2.Close(); |
| } |
| |
| private System.String[] docFields = new System.String[]{"w1 w2 w3 w4 w5", "w1 w3 w2 w3", "w1 xx w2 yy w3", "w1 w3 xx w2 yy w3"}; |
| |
| public virtual Query MakeQuery(System.String queryText) |
| { |
| Query q = (new QueryParser(Util.Version.LUCENE_CURRENT, field, new WhitespaceAnalyzer())).Parse(queryText); |
| return q; |
| } |
| |
| public virtual void QueriesTest(System.String queryText, int[] expDocNrs) |
| { |
| //System.out.println(); |
| //System.out.println("Query: " + queryText); |
| Query query1 = MakeQuery(queryText); |
| TopScoreDocCollector collector = TopScoreDocCollector.Create(1000, false); |
| searcher.Search(query1, null, collector); |
| ScoreDoc[] hits1 = collector.TopDocs().ScoreDocs; |
| |
| Query query2 = MakeQuery(queryText); // there should be no need to parse again... |
| collector = TopScoreDocCollector.Create(1000, true); |
| searcher.Search(query2, null, collector); |
| ScoreDoc[] hits2 = collector.TopDocs().ScoreDocs; |
| |
| Assert.AreEqual(mulFactor*collector.internalTotalHits, bigSearcher.Search(query1, 1).TotalHits); |
| |
| CheckHits.CheckHitsQuery(query2, hits1, hits2, expDocNrs); |
| } |
| |
| [Test] |
| public virtual void TestQueries01() |
| { |
| System.String queryText = "+w3 +xx"; |
| int[] expDocNrs = new int[]{2, 3}; |
| QueriesTest(queryText, expDocNrs); |
| } |
| |
| [Test] |
| public virtual void TestQueries02() |
| { |
| System.String queryText = "+w3 xx"; |
| int[] expDocNrs = new int[]{2, 3, 1, 0}; |
| QueriesTest(queryText, expDocNrs); |
| } |
| |
| [Test] |
| public virtual void TestQueries03() |
| { |
| System.String queryText = "w3 xx"; |
| int[] expDocNrs = new int[]{2, 3, 1, 0}; |
| QueriesTest(queryText, expDocNrs); |
| } |
| |
| [Test] |
| public virtual void TestQueries04() |
| { |
| System.String queryText = "w3 -xx"; |
| int[] expDocNrs = new int[]{1, 0}; |
| QueriesTest(queryText, expDocNrs); |
| } |
| |
| [Test] |
| public virtual void TestQueries05() |
| { |
| System.String queryText = "+w3 -xx"; |
| int[] expDocNrs = new int[]{1, 0}; |
| QueriesTest(queryText, expDocNrs); |
| } |
| |
| [Test] |
| public virtual void TestQueries06() |
| { |
| System.String queryText = "+w3 -xx -w5"; |
| int[] expDocNrs = new int[]{1}; |
| QueriesTest(queryText, expDocNrs); |
| } |
| |
| [Test] |
| public virtual void TestQueries07() |
| { |
| System.String queryText = "-w3 -xx -w5"; |
| int[] expDocNrs = new int[]{}; |
| QueriesTest(queryText, expDocNrs); |
| } |
| |
| [Test] |
| public virtual void TestQueries08() |
| { |
| System.String queryText = "+w3 xx -w5"; |
| int[] expDocNrs = new int[]{2, 3, 1}; |
| QueriesTest(queryText, expDocNrs); |
| } |
| |
| [Test] |
| public virtual void TestQueries09() |
| { |
| System.String queryText = "+w3 +xx +w2 zz"; |
| int[] expDocNrs = new int[]{2, 3}; |
| QueriesTest(queryText, expDocNrs); |
| } |
| |
| [Test] |
| public virtual void TestQueries10() |
| { |
| System.String queryText = "+w3 +xx +w2 zz"; |
| int[] expDocNrs = new int[]{2, 3}; |
| searcher.Similarity = new AnonymousClassDefaultSimilarity(this); |
| QueriesTest(queryText, expDocNrs); |
| } |
| |
| [Test] |
| public virtual void TestRandomQueries() |
| { |
| System.Random rnd = NewRandom(); |
| |
| System.String[] vals = new System.String[]{"w1", "w2", "w3", "w4", "w5", "xx", "yy", "zzz"}; |
| |
| int tot = 0; |
| |
| BooleanQuery q1 = null; |
| try |
| { |
| |
| // increase number of iterations for more complete testing |
| for (int i = 0; i < 1000; i++) |
| { |
| int level = rnd.Next(3); |
| q1 = RandBoolQuery(new System.Random(rnd.Next(System.Int32.MaxValue)), rnd.Next(0, 2) == 0 ? false : true, level, field, vals, null); |
| |
| // Can't sort by relevance since floating point numbers may not quite |
| // match up. |
| Sort sort = Sort.INDEXORDER; |
| |
| QueryUtils.Check(q1, searcher); |
| |
| TopFieldCollector collector = TopFieldCollector.Create(sort, 1000, false, true, true, true); |
| searcher.Search(q1, null, collector); |
| ScoreDoc[] hits1 = collector.TopDocs().ScoreDocs; |
| |
| collector = TopFieldCollector.Create(sort, 1000, false, true, true, false); |
| searcher.Search(q1, null, collector); |
| ScoreDoc[] hits2 = collector.TopDocs().ScoreDocs; |
| tot += hits2.Length; |
| CheckHits.CheckEqual(q1, hits1, hits2); |
| |
| BooleanQuery q3 = new BooleanQuery(); |
| q3.Add(q1, Occur.SHOULD); |
| q3.Add(new PrefixQuery(new Term("field2", "b")), Occur.SHOULD); |
| TopDocs hits4 = bigSearcher.Search(q3, 1); |
| Assert.AreEqual(mulFactor*collector.internalTotalHits + NUM_EXTRA_DOCS/2, hits4.TotalHits); |
| } |
| } |
| catch (System.Exception e) |
| { |
| // For easier debugging |
| System.Console.Out.WriteLine("failed query: " + q1); |
| throw e; |
| } |
| |
| // System.out.println("Total hits:"+tot); |
| } |
| |
| |
| // used to set properties or change every BooleanQuery |
| // generated from randBoolQuery. |
| public interface Callback |
| { |
| void PostCreate(BooleanQuery q); |
| } |
| |
| // Random rnd is passed in so that the exact same random query may be created |
| // more than once. |
| public static BooleanQuery RandBoolQuery(System.Random rnd, bool allowMust, int level, System.String field, System.String[] vals, TestBoolean2.Callback cb) |
| { |
| BooleanQuery current = new BooleanQuery(rnd.Next() < 0); |
| for (int i = 0; i < rnd.Next(vals.Length) + 1; i++) |
| { |
| int qType = 0; // term query |
| if (level > 0) |
| { |
| qType = rnd.Next(10); |
| } |
| Query q; |
| if (qType < 3) |
| { |
| q = new TermQuery(new Term(field, vals[rnd.Next(vals.Length)])); |
| } |
| else if (qType < 7) |
| { |
| q = new WildcardQuery(new Term(field, "w*")); |
| } |
| else |
| { |
| q = RandBoolQuery(rnd, allowMust, level - 1, field, vals, cb); |
| } |
| |
| int r = rnd.Next(10); |
| Occur occur; |
| if (r < 2) |
| { |
| occur = Occur.MUST_NOT; |
| } |
| else if (r < 5) |
| { |
| occur = allowMust ? Occur.MUST : Occur.SHOULD; |
| } |
| else |
| { |
| occur = Occur.SHOULD; |
| } |
| |
| current.Add(q, occur); |
| } |
| if (cb != null) |
| cb.PostCreate(current); |
| return current; |
| } |
| } |
| } |