| using NUnit.Framework; |
| using System; |
| using Assert = Lucene.Net.TestFramework.Assert; |
| |
| namespace Lucene.Net.Facet |
| { |
| |
| /* |
| * 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 Directory = Lucene.Net.Store.Directory; |
| using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader; |
| using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter; |
| using Document = Lucene.Net.Documents.Document; |
| using Field = Lucene.Net.Documents.Field; |
| using IndexReader = Lucene.Net.Index.IndexReader; |
| using IndexSearcher = Lucene.Net.Search.IndexSearcher; |
| using IOUtils = Lucene.Net.Util.IOUtils; |
| using ITaxonomyWriter = Lucene.Net.Facet.Taxonomy.ITaxonomyWriter; |
| using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery; |
| using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer; |
| using MockTokenizer = Lucene.Net.Analysis.MockTokenizer; |
| using Query = Lucene.Net.Search.Query; |
| using QueryUtils = Lucene.Net.Search.QueryUtils; |
| using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter; |
| using ScoreDoc = Lucene.Net.Search.ScoreDoc; |
| using Term = Lucene.Net.Index.Term; |
| using TermQuery = Lucene.Net.Search.TermQuery; |
| using TextField = Lucene.Net.Documents.TextField; |
| using TopDocs = Lucene.Net.Search.TopDocs; |
| |
| [TestFixture] |
| public class TestDrillDownQuery : FacetTestCase |
| { |
| |
| private static IndexReader reader; |
| private static DirectoryTaxonomyReader taxo; |
| private static Directory dir; |
| private static Directory taxoDir; |
| private static FacetsConfig config; |
| |
| |
| [OneTimeTearDown] |
| public override void AfterClass() // LUCENENET specific - renamed from AfterClassDrillDownQueryTest() to ensure calling order |
| { |
| IOUtils.Dispose(reader, taxo, dir, taxoDir); |
| reader = null; |
| taxo = null; |
| dir = null; |
| taxoDir = null; |
| config = null; |
| |
| base.AfterClass(); |
| } |
| |
| [OneTimeSetUp] |
| public override void BeforeClass() // LUCENENET specific - renamed from BeforeClassDrillDownQueryTest() to ensure calling order |
| { |
| base.BeforeClass(); |
| |
| dir = NewDirectory(); |
| Random r = Random; |
| RandomIndexWriter writer = new RandomIndexWriter(r, dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(r, MockTokenizer.KEYWORD, false))); |
| |
| taxoDir = NewDirectory(); |
| ITaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir); |
| config = new FacetsConfig(); |
| |
| // Randomize the per-dim config: |
| config.SetHierarchical("a", Random.NextBoolean()); |
| config.SetMultiValued("a", Random.NextBoolean()); |
| if (Random.NextBoolean()) |
| { |
| config.SetIndexFieldName("a", "$a"); |
| } |
| config.SetRequireDimCount("a", true); |
| |
| config.SetHierarchical("b", Random.NextBoolean()); |
| config.SetMultiValued("b", Random.NextBoolean()); |
| if (Random.NextBoolean()) |
| { |
| config.SetIndexFieldName("b", "$b"); |
| } |
| config.SetRequireDimCount("b", true); |
| |
| for (int i = 0; i < 100; i++) |
| { |
| Document doc = new Document(); |
| if (i % 2 == 0) // 50 |
| { |
| doc.Add(new TextField("content", "foo", Field.Store.NO)); |
| } |
| if (i % 3 == 0) // 33 |
| { |
| doc.Add(new TextField("content", "bar", Field.Store.NO)); |
| } |
| if (i % 4 == 0) // 25 |
| { |
| if (r.NextBoolean()) |
| { |
| doc.Add(new FacetField("a", "1")); |
| } |
| else |
| { |
| doc.Add(new FacetField("a", "2")); |
| } |
| } |
| if (i % 5 == 0) // 20 |
| { |
| doc.Add(new FacetField("b", "1")); |
| } |
| writer.AddDocument(config.Build(taxoWriter, doc)); |
| } |
| |
| taxoWriter.Dispose(); |
| reader = writer.GetReader(); |
| writer.Dispose(); |
| |
| taxo = new DirectoryTaxonomyReader(taxoDir); |
| } |
| |
| [Test] |
| public virtual void TestAndOrs() |
| { |
| IndexSearcher searcher = NewSearcher(reader); |
| |
| // test (a/1 OR a/2) AND b/1 |
| DrillDownQuery q = new DrillDownQuery(config); |
| q.Add("a", "1"); |
| q.Add("a", "2"); |
| q.Add("b", "1"); |
| TopDocs docs = searcher.Search(q, 100); |
| Assert.AreEqual(5, docs.TotalHits); |
| } |
| |
| [Test] |
| public virtual void TestQuery() |
| { |
| IndexSearcher searcher = NewSearcher(reader); |
| |
| // Making sure the query yields 25 documents with the facet "a" |
| DrillDownQuery q = new DrillDownQuery(config); |
| q.Add("a"); |
| QueryUtils.Check(q); |
| TopDocs docs = searcher.Search(q, 100); |
| Assert.AreEqual(25, docs.TotalHits); |
| |
| // Making sure the query yields 5 documents with the facet "b" and the |
| // previous (facet "a") query as a base query |
| DrillDownQuery q2 = new DrillDownQuery(config, q); |
| q2.Add("b"); |
| docs = searcher.Search(q2, 100); |
| Assert.AreEqual(5, docs.TotalHits); |
| |
| // Making sure that a query of both facet "a" and facet "b" yields 5 results |
| DrillDownQuery q3 = new DrillDownQuery(config); |
| q3.Add("a"); |
| q3.Add("b"); |
| docs = searcher.Search(q3, 100); |
| |
| Assert.AreEqual(5, docs.TotalHits); |
| // Check that content:foo (which yields 50% results) and facet/b (which yields 20%) |
| // would gather together 10 results (10%..) |
| Query fooQuery = new TermQuery(new Term("content", "foo")); |
| DrillDownQuery q4 = new DrillDownQuery(config, fooQuery); |
| q4.Add("b"); |
| docs = searcher.Search(q4, 100); |
| Assert.AreEqual(10, docs.TotalHits); |
| } |
| |
| [Test] |
| public virtual void TestQueryImplicitDefaultParams() |
| { |
| IndexSearcher searcher = NewSearcher(reader); |
| |
| // Create the base query to start with |
| DrillDownQuery q = new DrillDownQuery(config); |
| q.Add("a"); |
| |
| // Making sure the query yields 5 documents with the facet "b" and the |
| // previous (facet "a") query as a base query |
| DrillDownQuery q2 = new DrillDownQuery(config, q); |
| q2.Add("b"); |
| TopDocs docs = searcher.Search(q2, 100); |
| Assert.AreEqual(5, docs.TotalHits); |
| |
| // Check that content:foo (which yields 50% results) and facet/b (which yields 20%) |
| // would gather together 10 results (10%..) |
| Query fooQuery = new TermQuery(new Term("content", "foo")); |
| DrillDownQuery q4 = new DrillDownQuery(config, fooQuery); |
| q4.Add("b"); |
| docs = searcher.Search(q4, 100); |
| Assert.AreEqual(10, docs.TotalHits); |
| } |
| |
| [Test] |
| public virtual void TestScoring() |
| { |
| // verify that drill-down queries do not modify scores |
| IndexSearcher searcher = NewSearcher(reader); |
| |
| float[] scores = new float[reader.MaxDoc]; |
| |
| Query q = new TermQuery(new Term("content", "foo")); |
| TopDocs docs = searcher.Search(q, reader.MaxDoc); // fetch all available docs to this query |
| foreach (ScoreDoc sd in docs.ScoreDocs) |
| { |
| scores[sd.Doc] = sd.Score; |
| } |
| |
| // create a drill-down query with category "a", scores should not change |
| DrillDownQuery q2 = new DrillDownQuery(config, q); |
| q2.Add("a"); |
| docs = searcher.Search(q2, reader.MaxDoc); // fetch all available docs to this query |
| foreach (ScoreDoc sd in docs.ScoreDocs) |
| { |
| Assert.AreEqual(scores[sd.Doc], sd.Score, 0f, "score of doc=" + sd.Doc + " modified"); |
| } |
| } |
| |
| [Test] |
| public virtual void TestScoringNoBaseQuery() |
| { |
| // verify that drill-down queries (with no base query) returns 0.0 score |
| IndexSearcher searcher = NewSearcher(reader); |
| |
| DrillDownQuery q = new DrillDownQuery(config); |
| q.Add("a"); |
| TopDocs docs = searcher.Search(q, reader.MaxDoc); // fetch all available docs to this query |
| foreach (ScoreDoc sd in docs.ScoreDocs) |
| { |
| Assert.AreEqual(0f, sd.Score, 0f); |
| } |
| } |
| |
| [Test] |
| public virtual void TestTermNonDefault() |
| { |
| string aField = config.GetDimConfig("a").IndexFieldName; |
| Term termA = DrillDownQuery.Term(aField, "a"); |
| Assert.AreEqual(new Term(aField, "a"), termA); |
| |
| string bField = config.GetDimConfig("b").IndexFieldName; |
| Term termB = DrillDownQuery.Term(bField, "b"); |
| Assert.AreEqual(new Term(bField, "b"), termB); |
| } |
| |
| [Test] |
| public virtual void TestClone() |
| { |
| var q = new DrillDownQuery(config, new MatchAllDocsQuery()); |
| q.Add("a"); |
| |
| var clone = q.Clone() as DrillDownQuery; |
| Assert.NotNull(clone); |
| clone.Add("b"); |
| Assert.False(q.ToString().Equals(clone.ToString(), StringComparison.Ordinal), "query wasn't cloned: source=" + q + " clone=" + clone); |
| } |
| |
| [Test] |
| public virtual void TestNoDrillDown() |
| { |
| Query @base = new MatchAllDocsQuery(); |
| DrillDownQuery q = new DrillDownQuery(config, @base); |
| Query rewrite = q.Rewrite(reader).Rewrite(reader); |
| Assert.AreSame(@base, rewrite); |
| } |
| } |
| |
| } |