http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96822396/src/Lucene.Net.Tests/Search/TestMultiTermConstantScore.cs ---------------------------------------------------------------------- diff --git a/src/Lucene.Net.Tests/Search/TestMultiTermConstantScore.cs b/src/Lucene.Net.Tests/Search/TestMultiTermConstantScore.cs new file mode 100644 index 0000000..5aeaf7c --- /dev/null +++ b/src/Lucene.Net.Tests/Search/TestMultiTermConstantScore.cs @@ -0,0 +1,563 @@ +using System; +using Lucene.Net.Documents; + +namespace Lucene.Net.Search +{ + using NUnit.Framework; + using AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext; + using DefaultSimilarity = Lucene.Net.Search.Similarities.DefaultSimilarity; + using Directory = Lucene.Net.Store.Directory; + using Document = Documents.Document; + using Field = Field; + using FieldType = FieldType; + using IndexReader = Lucene.Net.Index.IndexReader; + + /* + * 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 MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer; + using MockTokenizer = Lucene.Net.Analysis.MockTokenizer; + using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter; + using Term = Lucene.Net.Index.Term; + using TextField = TextField; + + [TestFixture] + public class TestMultiTermConstantScore : BaseTestRangeFilter + { + /// <summary> + /// threshold for comparing floats </summary> + public const float SCORE_COMP_THRESH = 1e-6f; + + internal static Directory Small; + internal static IndexReader Reader; + + public static void AssertEquals(string m, int e, int a) + { + Assert.AreEqual(e, a, m); + } + + /// <summary> + /// LUCENENET specific + /// Is non-static because NewIndexWriterConfig is no longer static. + /// </summary> + [OneTimeSetUp] + public void BeforeClass() + { + string[] data = new string[] { "A 1 2 3 4 5 6", "Z 4 5 6", null, "B 2 4 5 6", "Y 3 5 6", null, "C 3 6", "X 4 5 6" }; + + Small = NewDirectory(); + RandomIndexWriter writer = new RandomIndexWriter(Random(), Small, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random(), MockTokenizer.WHITESPACE, false)).SetMergePolicy(NewLogMergePolicy())); + + FieldType customType = new FieldType(TextField.TYPE_STORED); + customType.IsTokenized = false; + for (int i = 0; i < data.Length; i++) + { + Document doc = new Document(); + doc.Add(NewField("id", Convert.ToString(i), customType)); // Field.Keyword("id",String.valueOf(i))); + doc.Add(NewField("all", "all", customType)); // Field.Keyword("all","all")); + if (null != data[i]) + { + doc.Add(NewTextField("data", data[i], Field.Store.YES)); // Field.Text("data",data[i])); + } + writer.AddDocument(doc); + } + + Reader = writer.Reader; + writer.Dispose(); + } + + [OneTimeTearDown] + public static void AfterClass() + { + Reader.Dispose(); + Small.Dispose(); + Reader = null; + Small = null; + } + + /// <summary> + /// macro for readability </summary> + public static Query Csrq(string f, string l, string h, bool il, bool ih) + { + TermRangeQuery query = TermRangeQuery.NewStringRange(f, l, h, il, ih); + query.MultiTermRewriteMethod = (MultiTermQuery.CONSTANT_SCORE_FILTER_REWRITE); + if (VERBOSE) + { + Console.WriteLine("TEST: query=" + query); + } + return query; + } + + public static Query Csrq(string f, string l, string h, bool il, bool ih, MultiTermQuery.RewriteMethod method) + { + TermRangeQuery query = TermRangeQuery.NewStringRange(f, l, h, il, ih); + query.MultiTermRewriteMethod = (method); + if (VERBOSE) + { + Console.WriteLine("TEST: query=" + query + " method=" + method); + } + return query; + } + + /// <summary> + /// macro for readability </summary> + public static Query Cspq(Term prefix) + { + PrefixQuery query = new PrefixQuery(prefix); + query.MultiTermRewriteMethod = (MultiTermQuery.CONSTANT_SCORE_FILTER_REWRITE); + return query; + } + + /// <summary> + /// macro for readability </summary> + public static Query Cswcq(Term wild) + { + WildcardQuery query = new WildcardQuery(wild); + query.MultiTermRewriteMethod = (MultiTermQuery.CONSTANT_SCORE_FILTER_REWRITE); + return query; + } + + [Test] + public virtual void TestBasics() + { + QueryUtils.Check(Csrq("data", "1", "6", T, T)); + QueryUtils.Check(Csrq("data", "A", "Z", T, T)); + QueryUtils.CheckUnequal(Csrq("data", "1", "6", T, T), Csrq("data", "A", "Z", T, T)); + + QueryUtils.Check(Cspq(new Term("data", "p*u?"))); + QueryUtils.CheckUnequal(Cspq(new Term("data", "pre*")), Cspq(new Term("data", "pres*"))); + + QueryUtils.Check(Cswcq(new Term("data", "p"))); + QueryUtils.CheckUnequal(Cswcq(new Term("data", "pre*n?t")), Cswcq(new Term("data", "pr*t?j"))); + } + + [Test] + public virtual void TestEqualScores() + { + // NOTE: uses index build in *this* setUp + + IndexSearcher search = NewSearcher(Reader); + + ScoreDoc[] result; + + // some hits match more terms then others, score should be the same + + result = search.Search(Csrq("data", "1", "6", T, T), null, 1000).ScoreDocs; + int numHits = result.Length; + AssertEquals("wrong number of results", 6, numHits); + float score = result[0].Score; + for (int i = 1; i < numHits; i++) + { + Assert.AreEqual(score, result[i].Score, SCORE_COMP_THRESH, "score for " + i + " was not the same"); + } + + result = search.Search(Csrq("data", "1", "6", T, T, MultiTermQuery.CONSTANT_SCORE_BOOLEAN_QUERY_REWRITE), null, 1000).ScoreDocs; + numHits = result.Length; + AssertEquals("wrong number of results", 6, numHits); + for (int i = 0; i < numHits; i++) + { + Assert.AreEqual(score, result[i].Score, SCORE_COMP_THRESH, "score for " + i + " was not the same"); + } + + result = search.Search(Csrq("data", "1", "6", T, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, 1000).ScoreDocs; + numHits = result.Length; + AssertEquals("wrong number of results", 6, numHits); + for (int i = 0; i < numHits; i++) + { + Assert.AreEqual(score, result[i].Score, SCORE_COMP_THRESH, "score for " + i + " was not the same"); + } + } + + [Test] + public virtual void TestEqualScoresWhenNoHits() // Test for LUCENE-5245: Empty MTQ rewrites should have a consistent norm, so always need to return a CSQ! + { + // NOTE: uses index build in *this* setUp + + IndexSearcher search = NewSearcher(Reader); + + ScoreDoc[] result; + + TermQuery dummyTerm = new TermQuery(new Term("data", "1")); + + BooleanQuery bq = new BooleanQuery(); + bq.Add(dummyTerm, Occur.SHOULD); // hits one doc + bq.Add(Csrq("data", "#", "#", T, T), Occur.SHOULD); // hits no docs + result = search.Search(bq, null, 1000).ScoreDocs; + int numHits = result.Length; + AssertEquals("wrong number of results", 1, numHits); + float score = result[0].Score; + for (int i = 1; i < numHits; i++) + { + Assert.AreEqual(score, result[i].Score, SCORE_COMP_THRESH, "score for " + i + " was not the same"); + } + + bq = new BooleanQuery(); + bq.Add(dummyTerm, Occur.SHOULD); // hits one doc + bq.Add(Csrq("data", "#", "#", T, T, MultiTermQuery.CONSTANT_SCORE_BOOLEAN_QUERY_REWRITE), Occur.SHOULD); // hits no docs + result = search.Search(bq, null, 1000).ScoreDocs; + numHits = result.Length; + AssertEquals("wrong number of results", 1, numHits); + for (int i = 0; i < numHits; i++) + { + Assert.AreEqual(score, result[i].Score, SCORE_COMP_THRESH, "score for " + i + " was not the same"); + } + + bq = new BooleanQuery(); + bq.Add(dummyTerm, Occur.SHOULD); // hits one doc + bq.Add(Csrq("data", "#", "#", T, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), Occur.SHOULD); // hits no docs + result = search.Search(bq, null, 1000).ScoreDocs; + numHits = result.Length; + AssertEquals("wrong number of results", 1, numHits); + for (int i = 0; i < numHits; i++) + { + Assert.AreEqual(score, result[i].Score, SCORE_COMP_THRESH, "score for " + i + " was not the same"); + } + } + + [Test] + public virtual void TestBoost() + { + // NOTE: uses index build in *this* setUp + + IndexSearcher search = NewSearcher(Reader); + + // test for correct application of query normalization + // must use a non score normalizing method for this. + + search.Similarity = new DefaultSimilarity(); + Query q = Csrq("data", "1", "6", T, T); + q.Boost = 100; + search.Search(q, null, new CollectorAnonymousInnerClassHelper(this)); + + // + // Ensure that boosting works to score one clause of a query higher + // than another. + // + Query q1 = Csrq("data", "A", "A", T, T); // matches document #0 + q1.Boost = .1f; + Query q2 = Csrq("data", "Z", "Z", T, T); // matches document #1 + BooleanQuery bq = new BooleanQuery(true); + bq.Add(q1, Occur.SHOULD); + bq.Add(q2, Occur.SHOULD); + + ScoreDoc[] hits = search.Search(bq, null, 1000).ScoreDocs; + Assert.AreEqual(1, hits[0].Doc); + Assert.AreEqual(0, hits[1].Doc); + Assert.IsTrue(hits[0].Score > hits[1].Score); + + q1 = Csrq("data", "A", "A", T, T, MultiTermQuery.CONSTANT_SCORE_BOOLEAN_QUERY_REWRITE); // matches document #0 + q1.Boost = .1f; + q2 = Csrq("data", "Z", "Z", T, T, MultiTermQuery.CONSTANT_SCORE_BOOLEAN_QUERY_REWRITE); // matches document #1 + bq = new BooleanQuery(true); + bq.Add(q1, Occur.SHOULD); + bq.Add(q2, Occur.SHOULD); + + hits = search.Search(bq, null, 1000).ScoreDocs; + Assert.AreEqual(1, hits[0].Doc); + Assert.AreEqual(0, hits[1].Doc); + Assert.IsTrue(hits[0].Score > hits[1].Score); + + q1 = Csrq("data", "A", "A", T, T); // matches document #0 + q1.Boost = 10f; + q2 = Csrq("data", "Z", "Z", T, T); // matches document #1 + bq = new BooleanQuery(true); + bq.Add(q1, Occur.SHOULD); + bq.Add(q2, Occur.SHOULD); + + hits = search.Search(bq, null, 1000).ScoreDocs; + Assert.AreEqual(0, hits[0].Doc); + Assert.AreEqual(1, hits[1].Doc); + Assert.IsTrue(hits[0].Score > hits[1].Score); + } + + private class CollectorAnonymousInnerClassHelper : ICollector + { + private readonly TestMultiTermConstantScore OuterInstance; + + public CollectorAnonymousInnerClassHelper(TestMultiTermConstantScore outerInstance) + { + this.OuterInstance = outerInstance; + @base = 0; + } + + private int @base; + private Scorer scorer; + + public virtual void SetScorer(Scorer scorer) + { + this.scorer = scorer; + } + + public virtual void Collect(int doc) + { + Assert.AreEqual(1.0f, scorer.GetScore(), SCORE_COMP_THRESH, "score for doc " + (doc + @base) + " was not correct"); + } + + public virtual void SetNextReader(AtomicReaderContext context) + { + @base = context.DocBase; + } + + public virtual bool AcceptsDocsOutOfOrder + { + get { return true; } + } + } + + [Test] + public virtual void TestBooleanOrderUnAffected() + { + // NOTE: uses index build in *this* setUp + + IndexSearcher search = NewSearcher(Reader); + + // first do a regular TermRangeQuery which uses term expansion so + // docs with more terms in range get higher scores + + Query rq = TermRangeQuery.NewStringRange("data", "1", "4", T, T); + + ScoreDoc[] expected = search.Search(rq, null, 1000).ScoreDocs; + int numHits = expected.Length; + + // now do a boolean where which also contains a + // ConstantScoreRangeQuery and make sure hte order is the same + + BooleanQuery q = new BooleanQuery(); + q.Add(rq, Occur.MUST); // T, F); + q.Add(Csrq("data", "1", "6", T, T), Occur.MUST); // T, F); + + ScoreDoc[] actual = search.Search(q, null, 1000).ScoreDocs; + + AssertEquals("wrong numebr of hits", numHits, actual.Length); + for (int i = 0; i < numHits; i++) + { + AssertEquals("mismatch in docid for hit#" + i, expected[i].Doc, actual[i].Doc); + } + } + + [Test] + public virtual void TestRangeQueryId() + { + // NOTE: uses index build in *super* setUp + + IndexReader reader = SignedIndexReader; + IndexSearcher search = NewSearcher(reader); + + if (VERBOSE) + { + Console.WriteLine("TEST: reader=" + reader); + } + + int medId = ((MaxId - MinId) / 2); + + string minIP = Pad(MinId); + string maxIP = Pad(MaxId); + string medIP = Pad(medId); + + int numDocs = reader.NumDocs; + + AssertEquals("num of docs", numDocs, 1 + MaxId - MinId); + + ScoreDoc[] result; + + // test id, bounded on both ends + + result = search.Search(Csrq("id", minIP, maxIP, T, T), null, numDocs).ScoreDocs; + AssertEquals("find all", numDocs, result.Length); + + result = search.Search(Csrq("id", minIP, maxIP, T, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).ScoreDocs; + AssertEquals("find all", numDocs, result.Length); + + result = search.Search(Csrq("id", minIP, maxIP, T, F), null, numDocs).ScoreDocs; + AssertEquals("all but last", numDocs - 1, result.Length); + + result = search.Search(Csrq("id", minIP, maxIP, T, F, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).ScoreDocs; + AssertEquals("all but last", numDocs - 1, result.Length); + + result = search.Search(Csrq("id", minIP, maxIP, F, T), null, numDocs).ScoreDocs; + AssertEquals("all but first", numDocs - 1, result.Length); + + result = search.Search(Csrq("id", minIP, maxIP, F, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).ScoreDocs; + AssertEquals("all but first", numDocs - 1, result.Length); + + result = search.Search(Csrq("id", minIP, maxIP, F, F), null, numDocs).ScoreDocs; + AssertEquals("all but ends", numDocs - 2, result.Length); + + result = search.Search(Csrq("id", minIP, maxIP, F, F, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).ScoreDocs; + AssertEquals("all but ends", numDocs - 2, result.Length); + + result = search.Search(Csrq("id", medIP, maxIP, T, T), null, numDocs).ScoreDocs; + AssertEquals("med and up", 1 + MaxId - medId, result.Length); + + result = search.Search(Csrq("id", medIP, maxIP, T, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).ScoreDocs; + AssertEquals("med and up", 1 + MaxId - medId, result.Length); + + result = search.Search(Csrq("id", minIP, medIP, T, T), null, numDocs).ScoreDocs; + AssertEquals("up to med", 1 + medId - MinId, result.Length); + + result = search.Search(Csrq("id", minIP, medIP, T, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).ScoreDocs; + AssertEquals("up to med", 1 + medId - MinId, result.Length); + + // unbounded id + + result = search.Search(Csrq("id", minIP, null, T, F), null, numDocs).ScoreDocs; + AssertEquals("min and up", numDocs, result.Length); + + result = search.Search(Csrq("id", null, maxIP, F, T), null, numDocs).ScoreDocs; + AssertEquals("max and down", numDocs, result.Length); + + result = search.Search(Csrq("id", minIP, null, F, F), null, numDocs).ScoreDocs; + AssertEquals("not min, but up", numDocs - 1, result.Length); + + result = search.Search(Csrq("id", null, maxIP, F, F), null, numDocs).ScoreDocs; + AssertEquals("not max, but down", numDocs - 1, result.Length); + + result = search.Search(Csrq("id", medIP, maxIP, T, F), null, numDocs).ScoreDocs; + AssertEquals("med and up, not max", MaxId - medId, result.Length); + + result = search.Search(Csrq("id", minIP, medIP, F, T), null, numDocs).ScoreDocs; + AssertEquals("not min, up to med", medId - MinId, result.Length); + + // very small sets + + result = search.Search(Csrq("id", minIP, minIP, F, F), null, numDocs).ScoreDocs; + AssertEquals("min,min,F,F", 0, result.Length); + + result = search.Search(Csrq("id", minIP, minIP, F, F, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).ScoreDocs; + AssertEquals("min,min,F,F", 0, result.Length); + + result = search.Search(Csrq("id", medIP, medIP, F, F), null, numDocs).ScoreDocs; + AssertEquals("med,med,F,F", 0, result.Length); + + result = search.Search(Csrq("id", medIP, medIP, F, F, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).ScoreDocs; + AssertEquals("med,med,F,F", 0, result.Length); + + result = search.Search(Csrq("id", maxIP, maxIP, F, F), null, numDocs).ScoreDocs; + AssertEquals("max,max,F,F", 0, result.Length); + + result = search.Search(Csrq("id", maxIP, maxIP, F, F, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).ScoreDocs; + AssertEquals("max,max,F,F", 0, result.Length); + + result = search.Search(Csrq("id", minIP, minIP, T, T), null, numDocs).ScoreDocs; + AssertEquals("min,min,T,T", 1, result.Length); + + result = search.Search(Csrq("id", minIP, minIP, T, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).ScoreDocs; + AssertEquals("min,min,T,T", 1, result.Length); + + result = search.Search(Csrq("id", null, minIP, F, T), null, numDocs).ScoreDocs; + AssertEquals("nul,min,F,T", 1, result.Length); + + result = search.Search(Csrq("id", null, minIP, F, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).ScoreDocs; + AssertEquals("nul,min,F,T", 1, result.Length); + + result = search.Search(Csrq("id", maxIP, maxIP, T, T), null, numDocs).ScoreDocs; + AssertEquals("max,max,T,T", 1, result.Length); + + result = search.Search(Csrq("id", maxIP, maxIP, T, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).ScoreDocs; + AssertEquals("max,max,T,T", 1, result.Length); + + result = search.Search(Csrq("id", maxIP, null, T, F), null, numDocs).ScoreDocs; + AssertEquals("max,nul,T,T", 1, result.Length); + + result = search.Search(Csrq("id", maxIP, null, T, F, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).ScoreDocs; + AssertEquals("max,nul,T,T", 1, result.Length); + + result = search.Search(Csrq("id", medIP, medIP, T, T), null, numDocs).ScoreDocs; + AssertEquals("med,med,T,T", 1, result.Length); + + result = search.Search(Csrq("id", medIP, medIP, T, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).ScoreDocs; + AssertEquals("med,med,T,T", 1, result.Length); + } + + [Test] + public virtual void TestRangeQueryRand() + { + // NOTE: uses index build in *super* setUp + + IndexReader reader = SignedIndexReader; + IndexSearcher search = NewSearcher(reader); + + string minRP = Pad(SignedIndexDir.MinR); + string maxRP = Pad(SignedIndexDir.MaxR); + + int numDocs = reader.NumDocs; + + AssertEquals("num of docs", numDocs, 1 + MaxId - MinId); + + ScoreDoc[] result; + + // test extremes, bounded on both ends + + result = search.Search(Csrq("rand", minRP, maxRP, T, T), null, numDocs).ScoreDocs; + AssertEquals("find all", numDocs, result.Length); + + result = search.Search(Csrq("rand", minRP, maxRP, T, F), null, numDocs).ScoreDocs; + AssertEquals("all but biggest", numDocs - 1, result.Length); + + result = search.Search(Csrq("rand", minRP, maxRP, F, T), null, numDocs).ScoreDocs; + AssertEquals("all but smallest", numDocs - 1, result.Length); + + result = search.Search(Csrq("rand", minRP, maxRP, F, F), null, numDocs).ScoreDocs; + AssertEquals("all but extremes", numDocs - 2, result.Length); + + // unbounded + + result = search.Search(Csrq("rand", minRP, null, T, F), null, numDocs).ScoreDocs; + AssertEquals("smallest and up", numDocs, result.Length); + + result = search.Search(Csrq("rand", null, maxRP, F, T), null, numDocs).ScoreDocs; + AssertEquals("biggest and down", numDocs, result.Length); + + result = search.Search(Csrq("rand", minRP, null, F, F), null, numDocs).ScoreDocs; + AssertEquals("not smallest, but up", numDocs - 1, result.Length); + + result = search.Search(Csrq("rand", null, maxRP, F, F), null, numDocs).ScoreDocs; + AssertEquals("not biggest, but down", numDocs - 1, result.Length); + + // very small sets + + result = search.Search(Csrq("rand", minRP, minRP, F, F), null, numDocs).ScoreDocs; + AssertEquals("min,min,F,F", 0, result.Length); + result = search.Search(Csrq("rand", maxRP, maxRP, F, F), null, numDocs).ScoreDocs; + AssertEquals("max,max,F,F", 0, result.Length); + + result = search.Search(Csrq("rand", minRP, minRP, T, T), null, numDocs).ScoreDocs; + AssertEquals("min,min,T,T", 1, result.Length); + result = search.Search(Csrq("rand", null, minRP, F, T), null, numDocs).ScoreDocs; + AssertEquals("nul,min,F,T", 1, result.Length); + + result = search.Search(Csrq("rand", maxRP, maxRP, T, T), null, numDocs).ScoreDocs; + AssertEquals("max,max,T,T", 1, result.Length); + result = search.Search(Csrq("rand", maxRP, null, T, F), null, numDocs).ScoreDocs; + AssertEquals("max,nul,T,T", 1, result.Length); + } + + + #region SorterTestBase + // LUCENENET NOTE: Tests in a base class are not pulled into the correct + // context in Visual Studio. This fixes that with the minimum amount of code necessary + // to run them in the correct context without duplicating all of the tests. + + [Test] + public override void TestPad() + { + base.TestPad(); + } + + #endregion + } +} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96822396/src/Lucene.Net.Tests/Search/TestMultiTermQueryRewrites.cs ---------------------------------------------------------------------- diff --git a/src/Lucene.Net.Tests/Search/TestMultiTermQueryRewrites.cs b/src/Lucene.Net.Tests/Search/TestMultiTermQueryRewrites.cs new file mode 100644 index 0000000..0d7afc5 --- /dev/null +++ b/src/Lucene.Net.Tests/Search/TestMultiTermQueryRewrites.cs @@ -0,0 +1,305 @@ +using System; +using System.Diagnostics; +using Lucene.Net.Documents; + +namespace Lucene.Net.Search +{ + using NUnit.Framework; + using System.Runtime.CompilerServices; + using Util; + using AttributeSource = Lucene.Net.Util.AttributeSource; + using BytesRef = Lucene.Net.Util.BytesRef; + using Directory = Lucene.Net.Store.Directory; + using DirectoryReader = Lucene.Net.Index.DirectoryReader; + using Document = Documents.Document; + using Field = Field; + using IndexReader = Lucene.Net.Index.IndexReader; + using LuceneTestCase = Lucene.Net.Util.LuceneTestCase; + + /* + * 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 MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer; + using MultiReader = Lucene.Net.Index.MultiReader; + using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter; + using Term = Lucene.Net.Index.Term; + using Terms = Lucene.Net.Index.Terms; + using TermsEnum = Lucene.Net.Index.TermsEnum; + + [TestFixture] + public class TestMultiTermQueryRewrites : LuceneTestCase + { + internal static Directory Dir, Sdir1, Sdir2; + internal static IndexReader Reader, MultiReader, MultiReaderDupls; + internal static IndexSearcher Searcher, MultiSearcher, MultiSearcherDupls; + + /// <summary> + /// LUCENENET specific + /// Is non-static because Similarity and TimeZone are not static. + /// </summary> + [OneTimeSetUp] + public void BeforeClass() + { + Dir = NewDirectory(); + Sdir1 = NewDirectory(); + Sdir2 = NewDirectory(); + RandomIndexWriter writer = new RandomIndexWriter(Random(), Dir, new MockAnalyzer(Random()), Similarity, TimeZone); + RandomIndexWriter swriter1 = new RandomIndexWriter(Random(), Sdir1, new MockAnalyzer(Random()), Similarity, TimeZone); + RandomIndexWriter swriter2 = new RandomIndexWriter(Random(), Sdir2, new MockAnalyzer(Random()), Similarity, TimeZone); + + for (int i = 0; i < 10; i++) + { + Document doc = new Document(); + doc.Add(NewStringField("data", Convert.ToString(i), Field.Store.NO)); + writer.AddDocument(doc); + ((i % 2 == 0) ? swriter1 : swriter2).AddDocument(doc); + } + writer.ForceMerge(1); + swriter1.ForceMerge(1); + swriter2.ForceMerge(1); + writer.Dispose(); + swriter1.Dispose(); + swriter2.Dispose(); + + Reader = DirectoryReader.Open(Dir); + Searcher = NewSearcher(Reader); + + MultiReader = new MultiReader(new IndexReader[] { DirectoryReader.Open(Sdir1), DirectoryReader.Open(Sdir2) }, true); + MultiSearcher = NewSearcher(MultiReader); + + MultiReaderDupls = new MultiReader(new IndexReader[] { DirectoryReader.Open(Sdir1), DirectoryReader.Open(Dir) }, true); + MultiSearcherDupls = NewSearcher(MultiReaderDupls); + } + + [OneTimeTearDown] + public static void AfterClass() + { + Reader.Dispose(); + MultiReader.Dispose(); + MultiReaderDupls.Dispose(); + Dir.Dispose(); + Sdir1.Dispose(); + Sdir2.Dispose(); + Reader = MultiReader = MultiReaderDupls = null; + Searcher = MultiSearcher = MultiSearcherDupls = null; + Dir = Sdir1 = Sdir2 = null; + } + + private Query ExtractInnerQuery(Query q) + { + if (q is ConstantScoreQuery) + { + // wrapped as ConstantScoreQuery + q = ((ConstantScoreQuery)q).Query; + } + return q; + } + + private Term ExtractTerm(Query q) + { + q = ExtractInnerQuery(q); + return ((TermQuery)q).Term; + } + + private void CheckBooleanQueryOrder(Query q) + { + q = ExtractInnerQuery(q); + BooleanQuery bq = (BooleanQuery)q; + Term last = null, act; + foreach (BooleanClause clause in bq.Clauses) + { + act = ExtractTerm(clause.Query); + if (last != null) + { + Assert.IsTrue(last.CompareTo(act) < 0, "sort order of terms in BQ violated"); + } + last = act; + } + } + + private void CheckDuplicateTerms(MultiTermQuery.RewriteMethod method) + { + MultiTermQuery mtq = TermRangeQuery.NewStringRange("data", "2", "7", true, true); + mtq.MultiTermRewriteMethod = (method); + Query q1 = Searcher.Rewrite(mtq); + Query q2 = MultiSearcher.Rewrite(mtq); + Query q3 = MultiSearcherDupls.Rewrite(mtq); + if (VERBOSE) + { + Console.WriteLine(); + Console.WriteLine("single segment: " + q1); + Console.WriteLine("multi segment: " + q2); + Console.WriteLine("multi segment with duplicates: " + q3); + } + Assert.IsTrue(q1.Equals(q2), "The multi-segment case must produce same rewritten query"); + Assert.IsTrue(q1.Equals(q3), "The multi-segment case with duplicates must produce same rewritten query"); + CheckBooleanQueryOrder(q1); + CheckBooleanQueryOrder(q2); + CheckBooleanQueryOrder(q3); + } + + [Test] + public virtual void TestRewritesWithDuplicateTerms() + { + CheckDuplicateTerms(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE); + + CheckDuplicateTerms(MultiTermQuery.CONSTANT_SCORE_BOOLEAN_QUERY_REWRITE); + + // use a large PQ here to only test duplicate terms and dont mix up when all scores are equal + CheckDuplicateTerms(new MultiTermQuery.TopTermsScoringBooleanQueryRewrite(1024)); + CheckDuplicateTerms(new MultiTermQuery.TopTermsBoostOnlyBooleanQueryRewrite(1024)); + + // Test auto rewrite (but only boolean mode), so we set the limits to large values to always get a BQ + MultiTermQuery.ConstantScoreAutoRewrite rewrite = new MultiTermQuery.ConstantScoreAutoRewrite(); + rewrite.TermCountCutoff = int.MaxValue; + rewrite.DocCountPercent = 100.0; + CheckDuplicateTerms(rewrite); + } + + private void CheckBooleanQueryBoosts(BooleanQuery bq) + { + foreach (BooleanClause clause in bq.Clauses) + { + TermQuery mtq = (TermQuery)clause.Query; + Assert.AreEqual(Convert.ToSingle(mtq.Term.Text()), mtq.Boost, 0, "Parallel sorting of boosts in rewrite mode broken"); + } + } + + private void CheckBoosts(MultiTermQuery.RewriteMethod method) + { + MultiTermQuery mtq = new MultiTermQueryAnonymousInnerClassHelper(this); + mtq.MultiTermRewriteMethod = (method); + Query q1 = Searcher.Rewrite(mtq); + Query q2 = MultiSearcher.Rewrite(mtq); + Query q3 = MultiSearcherDupls.Rewrite(mtq); + if (VERBOSE) + { + Console.WriteLine(); + Console.WriteLine("single segment: " + q1); + Console.WriteLine("multi segment: " + q2); + Console.WriteLine("multi segment with duplicates: " + q3); + } + Assert.IsTrue(q1.Equals(q2), "The multi-segment case must produce same rewritten query"); + Assert.IsTrue(q1.Equals(q3), "The multi-segment case with duplicates must produce same rewritten query"); + CheckBooleanQueryBoosts((BooleanQuery)q1); + CheckBooleanQueryBoosts((BooleanQuery)q2); + CheckBooleanQueryBoosts((BooleanQuery)q3); + } + + private class MultiTermQueryAnonymousInnerClassHelper : MultiTermQuery + { + private readonly TestMultiTermQueryRewrites OuterInstance; + + public MultiTermQueryAnonymousInnerClassHelper(TestMultiTermQueryRewrites outerInstance) + : base("data") + { + this.OuterInstance = outerInstance; + } + + protected override TermsEnum GetTermsEnum(Terms terms, AttributeSource atts) + { + return new TermRangeTermsEnumAnonymousInnerClassHelper(this, terms.GetIterator(null), new BytesRef("2"), new BytesRef("7")); + } + + private class TermRangeTermsEnumAnonymousInnerClassHelper : TermRangeTermsEnum + { + private readonly MultiTermQueryAnonymousInnerClassHelper OuterInstance; + + public TermRangeTermsEnumAnonymousInnerClassHelper(MultiTermQueryAnonymousInnerClassHelper outerInstance, TermsEnum iterator, BytesRef bref1, BytesRef bref2) + : base(iterator, bref1, bref2, true, true) + { + this.OuterInstance = outerInstance; + boostAtt = Attributes.AddAttribute<IBoostAttribute>(); + } + + internal readonly IBoostAttribute boostAtt; + + protected override AcceptStatus Accept(BytesRef term) + { + boostAtt.Boost = Convert.ToSingle(term.Utf8ToString()); + return base.Accept(term); + } + } + + public override string ToString(string field) + { + return "dummy"; + } + } + + [Test] + public virtual void TestBoosts() + { + CheckBoosts(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE); + + // use a large PQ here to only test boosts and dont mix up when all scores are equal + CheckBoosts(new MultiTermQuery.TopTermsScoringBooleanQueryRewrite(1024)); + } + + private void CheckMaxClauseLimitation(MultiTermQuery.RewriteMethod method, [CallerMemberName] string memberName = "") + { + int savedMaxClauseCount = BooleanQuery.MaxClauseCount; + BooleanQuery.MaxClauseCount = 3; + + MultiTermQuery mtq = TermRangeQuery.NewStringRange("data", "2", "7", true, true); + mtq.MultiTermRewriteMethod = (method); + try + { + MultiSearcherDupls.Rewrite(mtq); + Assert.Fail("Should throw BooleanQuery.TooManyClauses"); + } + catch (BooleanQuery.TooManyClauses e) + { + // Maybe remove this assert in later versions, when internal API changes: + Assert.AreEqual("CheckMaxClauseCount", new StackTrace(e, false).GetFrames()[0].GetMethod().Name); //, "Should throw BooleanQuery.TooManyClauses with a stacktrace containing checkMaxClauseCount()"); + } + finally + { + BooleanQuery.MaxClauseCount = savedMaxClauseCount; + } + } + + private void CheckNoMaxClauseLimitation(MultiTermQuery.RewriteMethod method) + { + int savedMaxClauseCount = BooleanQuery.MaxClauseCount; + BooleanQuery.MaxClauseCount = 3; + + MultiTermQuery mtq = TermRangeQuery.NewStringRange("data", "2", "7", true, true); + mtq.MultiTermRewriteMethod = (method); + try + { + MultiSearcherDupls.Rewrite(mtq); + } + finally + { + BooleanQuery.MaxClauseCount = savedMaxClauseCount; + } + } + + [Test] + public virtual void TestMaxClauseLimitations() + { + CheckMaxClauseLimitation(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE); + CheckMaxClauseLimitation(MultiTermQuery.CONSTANT_SCORE_BOOLEAN_QUERY_REWRITE); + + CheckNoMaxClauseLimitation(MultiTermQuery.CONSTANT_SCORE_FILTER_REWRITE); + CheckNoMaxClauseLimitation(MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT); + CheckNoMaxClauseLimitation(new MultiTermQuery.TopTermsScoringBooleanQueryRewrite(1024)); + CheckNoMaxClauseLimitation(new MultiTermQuery.TopTermsBoostOnlyBooleanQueryRewrite(1024)); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96822396/src/Lucene.Net.Tests/Search/TestMultiThreadTermVectors.cs ---------------------------------------------------------------------- diff --git a/src/Lucene.Net.Tests/Search/TestMultiThreadTermVectors.cs b/src/Lucene.Net.Tests/Search/TestMultiThreadTermVectors.cs new file mode 100644 index 0000000..89607cf --- /dev/null +++ b/src/Lucene.Net.Tests/Search/TestMultiThreadTermVectors.cs @@ -0,0 +1,244 @@ +using Lucene.Net.Documents; +using Lucene.Net.Support; +using System; +using System.Diagnostics; +using System.Text; +using System.Threading; + +namespace Lucene.Net.Search +{ + + using NUnit.Framework; + using System.IO; + using Directory = Lucene.Net.Store.Directory; + using DirectoryReader = Lucene.Net.Index.DirectoryReader; + using English = Lucene.Net.Util.English; + using Fields = Lucene.Net.Index.Fields; + using IndexReader = Lucene.Net.Index.IndexReader; + using IndexWriter = Lucene.Net.Index.IndexWriter; + using LuceneTestCase = Lucene.Net.Util.LuceneTestCase; + + /* + * 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 MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer; + using Terms = Lucene.Net.Index.Terms; + using TermsEnum = Lucene.Net.Index.TermsEnum; + + [TestFixture] + public class TestMultiThreadTermVectors : LuceneTestCase + { + private Directory Directory; + public int NumDocs = 100; + public int NumThreads = 3; + + [SetUp] + public override void SetUp() + { + base.SetUp(); + Directory = NewDirectory(); + IndexWriter writer = new IndexWriter(Directory, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy())); + //writer.setNoCFSRatio(0.0); + //writer.infoStream = System.out; + FieldType customType = new FieldType(TextField.TYPE_STORED); + customType.IsTokenized = false; + customType.StoreTermVectors = true; + for (int i = 0; i < NumDocs; i++) + { + Documents.Document doc = new Documents.Document(); + Field fld = NewField("field", English.IntToEnglish(i), customType); + doc.Add(fld); + writer.AddDocument(doc); + } + writer.Dispose(); + } + + [TearDown] + public override void TearDown() + { + Directory.Dispose(); + base.TearDown(); + } + + [Test] + public virtual void Test() + { + IndexReader reader = null; + + try + { + reader = DirectoryReader.Open(Directory); + for (int i = 1; i <= NumThreads; i++) + { + TestTermPositionVectors(reader, i); + } + } + catch (IOException ioe) + { + Assert.Fail(ioe.Message); + } + finally + { + if (reader != null) + { + try + { + /// <summary> + /// close the opened reader </summary> + reader.Dispose(); + } + catch (IOException ioe) + { + Console.WriteLine(ioe.ToString()); + Console.Write(ioe.StackTrace); + } + } + } + } + + public virtual void TestTermPositionVectors(IndexReader reader, int threadCount) + { + MultiThreadTermVectorsReader[] mtr = new MultiThreadTermVectorsReader[threadCount]; + for (int i = 0; i < threadCount; i++) + { + mtr[i] = new MultiThreadTermVectorsReader(); + mtr[i].Init(reader); + } + + // run until all threads finished + int threadsAlive = mtr.Length; + while (threadsAlive > 0) + { + //System.out.println("Threads alive"); + Thread.Sleep(10); + threadsAlive = mtr.Length; + for (int i = 0; i < mtr.Length; i++) + { + if (mtr[i].Alive == true) + { + break; + } + + threadsAlive--; + } + } + + long totalTime = 0L; + for (int i = 0; i < mtr.Length; i++) + { + totalTime += mtr[i].TimeElapsed; + mtr[i] = null; + } + + //System.out.println("threadcount: " + mtr.Length + " average term vector time: " + totalTime/mtr.Length); + } + } + + internal class MultiThreadTermVectorsReader : IThreadRunnable + { + private IndexReader Reader = null; + private ThreadClass t = null; + + private readonly int RunsToDo = 100; + internal long TimeElapsed = 0; + + public virtual void Init(IndexReader reader) + { + this.Reader = reader; + TimeElapsed = 0; + t = new ThreadClass(new System.Threading.ThreadStart(this.Run)); + t.Start(); + } + + public virtual bool Alive + { + get + { + if (t == null) + { + return false; + } + + return t.IsAlive; + } + } + + [Test] + public void Run() + { + try + { + // run the test 100 times + for (int i = 0; i < RunsToDo; i++) + { + TestTermVectors(); + } + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + Console.Write(e.StackTrace); + } + return; + } + + private void TestTermVectors() + { + // check: + int numDocs = Reader.NumDocs; + long start = 0L; + for (int docId = 0; docId < numDocs; docId++) + { + start = Environment.TickCount; + Fields vectors = Reader.GetTermVectors(docId); + TimeElapsed += Environment.TickCount - start; + + // verify vectors result + VerifyVectors(vectors, docId); + + start = Environment.TickCount; + Terms vector = Reader.GetTermVectors(docId).GetTerms("field"); + TimeElapsed += Environment.TickCount - start; + + VerifyVector(vector.GetIterator(null), docId); + } + } + + private void VerifyVectors(Fields vectors, int num) + { + foreach (string field in vectors) + { + Terms terms = vectors.GetTerms(field); + Debug.Assert(terms != null); + VerifyVector(terms.GetIterator(null), num); + } + } + + private void VerifyVector(TermsEnum vector, int num) + { + StringBuilder temp = new StringBuilder(); + while (vector.Next() != null) + { + temp.Append(vector.Term.Utf8ToString()); + } + if (!English.IntToEnglish(num).Trim().Equals(temp.ToString().Trim())) + { + Console.WriteLine("wrong term result"); + } + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96822396/src/Lucene.Net.Tests/Search/TestMultiValuedNumericRangeQuery.cs ---------------------------------------------------------------------- diff --git a/src/Lucene.Net.Tests/Search/TestMultiValuedNumericRangeQuery.cs b/src/Lucene.Net.Tests/Search/TestMultiValuedNumericRangeQuery.cs new file mode 100644 index 0000000..5c66182 --- /dev/null +++ b/src/Lucene.Net.Tests/Search/TestMultiValuedNumericRangeQuery.cs @@ -0,0 +1,88 @@ +using System.Globalization; +using Lucene.Net.Documents; + +namespace Lucene.Net.Search +{ + using NUnit.Framework; + using Directory = Lucene.Net.Store.Directory; + using Document = Documents.Document; + using Field = Field; + using IndexReader = Lucene.Net.Index.IndexReader; + using Int32Field = Int32Field; + using LuceneTestCase = Lucene.Net.Util.LuceneTestCase; + + /* + * 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 MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer; + using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter; + using TestUtil = Lucene.Net.Util.TestUtil; + + [TestFixture] + public class TestMultiValuedNumericRangeQuery : LuceneTestCase + { + /// <summary> + /// Tests NumericRangeQuery on a multi-valued field (multiple numeric values per document). + /// this test ensures, that a classical TermRangeQuery returns exactly the same document numbers as + /// NumericRangeQuery (see SOLR-1322 for discussion) and the multiple precision terms per numeric value + /// do not interfere with multiple numeric values. + /// </summary> + [Test] + public virtual void TestMultiValuedNRQ() + { + Directory directory = NewDirectory(); + RandomIndexWriter writer = new RandomIndexWriter(Random(), directory, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetMaxBufferedDocs(TestUtil.NextInt(Random(), 50, 1000))); + const string format = "D11"; + + int num = AtLeast(500); + for (int l = 0; l < num; l++) + { + Document doc = new Document(); + for (int m = 0, c = Random().Next(10); m <= c; m++) + { + int value = Random().Next(int.MaxValue); + doc.Add(NewStringField("asc", value.ToString(format), Field.Store.NO)); + doc.Add(new Int32Field("trie", value, Field.Store.NO)); + } + writer.AddDocument(doc); + } + IndexReader reader = writer.Reader; + writer.Dispose(); + + IndexSearcher searcher = NewSearcher(reader); + num = AtLeast(50); + for (int i = 0; i < num; i++) + { + int lower = Random().Next(int.MaxValue); + int upper = Random().Next(int.MaxValue); + if (lower > upper) + { + int a = lower; + lower = upper; + upper = a; + } + TermRangeQuery cq = TermRangeQuery.NewStringRange("asc", lower.ToString(format), upper.ToString(format), true, true); + NumericRangeQuery<int> tq = NumericRangeQuery.NewInt32Range("trie", lower, upper, true, true); + TopDocs trTopDocs = searcher.Search(cq, 1); + TopDocs nrTopDocs = searcher.Search(tq, 1); + Assert.AreEqual(trTopDocs.TotalHits, nrTopDocs.TotalHits, "Returned count for NumericRangeQuery and TermRangeQuery must be equal"); + } + reader.Dispose(); + directory.Dispose(); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96822396/src/Lucene.Net.Tests/Search/TestNGramPhraseQuery.cs ---------------------------------------------------------------------- diff --git a/src/Lucene.Net.Tests/Search/TestNGramPhraseQuery.cs b/src/Lucene.Net.Tests/Search/TestNGramPhraseQuery.cs new file mode 100644 index 0000000..c445929 --- /dev/null +++ b/src/Lucene.Net.Tests/Search/TestNGramPhraseQuery.cs @@ -0,0 +1,113 @@ +namespace Lucene.Net.Search +{ + using NUnit.Framework; + using Directory = Lucene.Net.Store.Directory; + + /* + * 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 DirectoryReader = Lucene.Net.Index.DirectoryReader; + using IndexReader = Lucene.Net.Index.IndexReader; + using LuceneTestCase = Lucene.Net.Util.LuceneTestCase; + using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter; + using Term = Lucene.Net.Index.Term; + + [TestFixture] + public class TestNGramPhraseQuery : LuceneTestCase + { + private static IndexReader Reader; + private static Directory Directory; + + /// <summary> + /// LUCENENET specific + /// Is non-static because Similarity and TimeZone are not static. + /// </summary> + [OneTimeSetUp] + public void BeforeClass() + { + Directory = NewDirectory(); + RandomIndexWriter writer = new RandomIndexWriter(Random(), Directory, Similarity, TimeZone); + writer.Dispose(); + Reader = DirectoryReader.Open(Directory); + } + + [OneTimeTearDown] + public static void AfterClass() + { + Reader.Dispose(); + Reader = null; + Directory.Dispose(); + Directory = null; + } + + [Test] + public virtual void TestRewrite() + { + // bi-gram test ABC => AB/BC => AB/BC + PhraseQuery pq1 = new NGramPhraseQuery(2); + pq1.Add(new Term("f", "AB")); + pq1.Add(new Term("f", "BC")); + + Query q = pq1.Rewrite(Reader); + Assert.IsTrue(q is NGramPhraseQuery); + Assert.AreSame(pq1, q); + pq1 = (NGramPhraseQuery)q; + Assert.AreEqual(new Term[] { new Term("f", "AB"), new Term("f", "BC") }, pq1.GetTerms()); + Assert.AreEqual(new int[] { 0, 1 }, pq1.GetPositions()); + + // bi-gram test ABCD => AB/BC/CD => AB//CD + PhraseQuery pq2 = new NGramPhraseQuery(2); + pq2.Add(new Term("f", "AB")); + pq2.Add(new Term("f", "BC")); + pq2.Add(new Term("f", "CD")); + + q = pq2.Rewrite(Reader); + Assert.IsTrue(q is PhraseQuery); + Assert.AreNotSame(pq2, q); + pq2 = (PhraseQuery)q; + Assert.AreEqual(new Term[] { new Term("f", "AB"), new Term("f", "CD") }, pq2.GetTerms()); + Assert.AreEqual(new int[] { 0, 2 }, pq2.GetPositions()); + + // tri-gram test ABCDEFGH => ABC/BCD/CDE/DEF/EFG/FGH => ABC///DEF//FGH + PhraseQuery pq3 = new NGramPhraseQuery(3); + pq3.Add(new Term("f", "ABC")); + pq3.Add(new Term("f", "BCD")); + pq3.Add(new Term("f", "CDE")); + pq3.Add(new Term("f", "DEF")); + pq3.Add(new Term("f", "EFG")); + pq3.Add(new Term("f", "FGH")); + + q = pq3.Rewrite(Reader); + Assert.IsTrue(q is PhraseQuery); + Assert.AreNotSame(pq3, q); + pq3 = (PhraseQuery)q; + Assert.AreEqual(new Term[] { new Term("f", "ABC"), new Term("f", "DEF"), new Term("f", "FGH") }, pq3.GetTerms()); + Assert.AreEqual(new int[] { 0, 3, 5 }, pq3.GetPositions()); + + // LUCENE-4970: boosting test + PhraseQuery pq4 = new NGramPhraseQuery(2); + pq4.Add(new Term("f", "AB")); + pq4.Add(new Term("f", "BC")); + pq4.Add(new Term("f", "CD")); + pq4.Boost = 100.0F; + + q = pq4.Rewrite(Reader); + Assert.AreNotSame(pq4, q); + Assert.AreEqual(pq4.Boost, q.Boost, 0.1f); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96822396/src/Lucene.Net.Tests/Search/TestNot.cs ---------------------------------------------------------------------- diff --git a/src/Lucene.Net.Tests/Search/TestNot.cs b/src/Lucene.Net.Tests/Search/TestNot.cs new file mode 100644 index 0000000..99611aa --- /dev/null +++ b/src/Lucene.Net.Tests/Search/TestNot.cs @@ -0,0 +1,65 @@ +using Lucene.Net.Documents; + +namespace Lucene.Net.Search +{ + using NUnit.Framework; + using Directory = Lucene.Net.Store.Directory; + using Document = Documents.Document; + + /* + * 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 Field = Field; + using IndexReader = Lucene.Net.Index.IndexReader; + using LuceneTestCase = Lucene.Net.Util.LuceneTestCase; + using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter; + using Term = Lucene.Net.Index.Term; + + /// <summary> + /// Similarity unit test. + /// + /// + /// </summary> + [TestFixture] + public class TestNot : LuceneTestCase + { + [Test] + public virtual void TestNot_Mem() + { + Directory store = NewDirectory(); + RandomIndexWriter writer = new RandomIndexWriter(Random(), store, Similarity, TimeZone); + + Document d1 = new Document(); + d1.Add(NewTextField("field", "a b", Field.Store.YES)); + + writer.AddDocument(d1); + IndexReader reader = writer.Reader; + + IndexSearcher searcher = NewSearcher(reader); + + BooleanQuery query = new BooleanQuery(); + query.Add(new TermQuery(new Term("field", "a")), Occur.SHOULD); + query.Add(new TermQuery(new Term("field", "b")), Occur.MUST_NOT); + + ScoreDoc[] hits = searcher.Search(query, null, 1000).ScoreDocs; + Assert.AreEqual(0, hits.Length); + writer.Dispose(); + reader.Dispose(); + store.Dispose(); + } + } +} \ No newline at end of file
