/* * 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 NUnit.Framework; 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 QueryParser = Lucene.Net.QueryParsers.QueryParser; using RAMDirectory = Lucene.Net.Store.RAMDirectory; using Analyzer = Lucene.Net.Analysis.Analyzer; using StopAnalyzer = Lucene.Net.Analysis.StopAnalyzer; using StopFilter = Lucene.Net.Analysis.StopFilter; using Token = Lucene.Net.Analysis.Token; using TokenStream = Lucene.Net.Analysis.TokenStream; using WhitespaceAnalyzer = Lucene.Net.Analysis.WhitespaceAnalyzer; using LuceneTestCase = Lucene.Net.Util.LuceneTestCase; namespace Lucene.Net.Search { /// Term position unit test. /// /// /// /// $Revision: 607591 $ /// [TestFixture] public class TestPositionIncrement : LuceneTestCase { private class AnonymousClassAnalyzer : Analyzer { public AnonymousClassAnalyzer(TestPositionIncrement enclosingInstance) { InitBlock(enclosingInstance); } private class AnonymousClassTokenStream : TokenStream { public AnonymousClassTokenStream(AnonymousClassAnalyzer enclosingInstance) { InitBlock(enclosingInstance); } private void InitBlock(AnonymousClassAnalyzer enclosingInstance) { this.enclosingInstance = enclosingInstance; } private AnonymousClassAnalyzer enclosingInstance; public AnonymousClassAnalyzer Enclosing_Instance { get { return enclosingInstance; } } private System.String[] TOKENS = new System.String[]{"1", "2", "3", "4", "5"}; private int[] INCREMENTS = new int[]{1, 2, 1, 0, 1}; private int i = 0; public override Token Next(Token reusableToken) { System.Diagnostics.Debug.Assert(reusableToken != null); if (i == TOKENS.Length) return null; reusableToken.Reinit(TOKENS[i], i, i); reusableToken.SetPositionIncrement(INCREMENTS[i]); i++; return reusableToken; } } private void InitBlock(TestPositionIncrement enclosingInstance) { this.enclosingInstance = enclosingInstance; } private TestPositionIncrement enclosingInstance; public TestPositionIncrement Enclosing_Instance { get { return enclosingInstance; } } public override TokenStream TokenStream(System.String fieldName, System.IO.TextReader reader) { return new AnonymousClassTokenStream(this); } } private class AnonymousClassAnalyzer1 : Analyzer { public AnonymousClassAnalyzer1(TestPositionIncrement enclosingInstance) { InitBlock(enclosingInstance); } private void InitBlock(TestPositionIncrement enclosingInstance) { this.enclosingInstance = enclosingInstance; } private TestPositionIncrement enclosingInstance; public TestPositionIncrement Enclosing_Instance { get { return enclosingInstance; } } internal WhitespaceAnalyzer a = new WhitespaceAnalyzer(); public override TokenStream TokenStream(System.String fieldName, System.IO.TextReader reader) { TokenStream ts = a.TokenStream(fieldName, reader); return new StopFilter(ts, new System.String[]{"stop"}); } } [Test] public virtual void TestSetPosition() { Analyzer analyzer = new AnonymousClassAnalyzer(this); RAMDirectory store = new RAMDirectory(); IndexWriter writer = new IndexWriter(store, analyzer, true, IndexWriter.MaxFieldLength.LIMITED); Document d = new Document(); d.Add(new Field("field", "bogus", Field.Store.YES, Field.Index.ANALYZED)); writer.AddDocument(d); writer.Optimize(); writer.Close(); IndexSearcher searcher = new IndexSearcher(store); PhraseQuery q; ScoreDoc[] hits; q = new PhraseQuery(); q.Add(new Term("field", "1")); q.Add(new Term("field", "2")); hits = searcher.Search(q, null, 1000).scoreDocs; Assert.AreEqual(0, hits.Length); // same as previous, just specify positions explicitely. q = new PhraseQuery(); q.Add(new Term("field", "1"), 0); q.Add(new Term("field", "2"), 1); hits = searcher.Search(q, null, 1000).scoreDocs; Assert.AreEqual(0, hits.Length); // specifying correct positions should find the phrase. q = new PhraseQuery(); q.Add(new Term("field", "1"), 0); q.Add(new Term("field", "2"), 2); hits = searcher.Search(q, null, 1000).scoreDocs; Assert.AreEqual(1, hits.Length); q = new PhraseQuery(); q.Add(new Term("field", "2")); q.Add(new Term("field", "3")); hits = searcher.Search(q, null, 1000).scoreDocs; Assert.AreEqual(1, hits.Length); q = new PhraseQuery(); q.Add(new Term("field", "3")); q.Add(new Term("field", "4")); hits = searcher.Search(q, null, 1000).scoreDocs; Assert.AreEqual(0, hits.Length); // phrase query would find it when correct positions are specified. q = new PhraseQuery(); q.Add(new Term("field", "3"), 0); q.Add(new Term("field", "4"), 0); hits = searcher.Search(q, null, 1000).scoreDocs; Assert.AreEqual(1, hits.Length); // phrase query should fail for non existing searched term // even if there exist another searched terms in the same searched position. q = new PhraseQuery(); q.Add(new Term("field", "3"), 0); q.Add(new Term("field", "9"), 0); hits = searcher.Search(q, null, 1000).scoreDocs; Assert.AreEqual(0, hits.Length); // multi-phrase query should succed for non existing searched term // because there exist another searched terms in the same searched position. MultiPhraseQuery mq = new MultiPhraseQuery(); mq.Add(new Term[]{new Term("field", "3"), new Term("field", "9")}, 0); hits = searcher.Search(mq, null, 1000).scoreDocs; Assert.AreEqual(1, hits.Length); q = new PhraseQuery(); q.Add(new Term("field", "2")); q.Add(new Term("field", "4")); hits = searcher.Search(q, null, 1000).scoreDocs; Assert.AreEqual(1, hits.Length); q = new PhraseQuery(); q.Add(new Term("field", "3")); q.Add(new Term("field", "5")); hits = searcher.Search(q, null, 1000).scoreDocs; Assert.AreEqual(1, hits.Length); q = new PhraseQuery(); q.Add(new Term("field", "4")); q.Add(new Term("field", "5")); hits = searcher.Search(q, null, 1000).scoreDocs; Assert.AreEqual(1, hits.Length); q = new PhraseQuery(); q.Add(new Term("field", "2")); q.Add(new Term("field", "5")); hits = searcher.Search(q, null, 1000).scoreDocs; Assert.AreEqual(0, hits.Length); // analyzer to introduce stopwords and increment gaps Analyzer stpa = new AnonymousClassAnalyzer1(this); // should not find "1 2" because there is a gap of 1 in the index Lucene.Net.QueryParsers.QueryParser qp = new Lucene.Net.QueryParsers.QueryParser("field", stpa); q = (PhraseQuery) qp.Parse("\"1 2\""); hits = searcher.Search(q, null, 1000).scoreDocs; Assert.AreEqual(0, hits.Length); // omitted stop word cannot help because stop filter swallows the increments. q = (PhraseQuery) qp.Parse("\"1 stop 2\""); hits = searcher.Search(q, null, 1000).scoreDocs; Assert.AreEqual(0, hits.Length); // query parser alone won't help, because stop filter swallows the increments. bool dflt = StopFilter.GetEnablePositionIncrementsDefault(); StopFilter.SetEnablePositionIncrementsDefault(false); qp.SetEnablePositionIncrements(true); q = (PhraseQuery) qp.Parse("\"1 stop 2\""); hits = searcher.Search(q, null, 1000).scoreDocs; Assert.AreEqual(0, hits.Length); try { // stop filter alone won't help, because query parser swallows the increments. qp.SetEnablePositionIncrements(false); StopFilter.SetEnablePositionIncrementsDefault(true); q = (PhraseQuery) qp.Parse("\"1 stop 2\""); hits = searcher.Search(q, null, 1000).scoreDocs; Assert.AreEqual(0, hits.Length); // when both qp qnd stopFilter propagate increments, we should find the doc. qp.SetEnablePositionIncrements(true); q = (PhraseQuery) qp.Parse("\"1 stop 2\""); hits = searcher.Search(q, null, 1000).scoreDocs; Assert.AreEqual(1, hits.Length); } finally { StopFilter.SetEnablePositionIncrementsDefault(dflt); } } /// Basic analyzer behavior should be to keep sequential terms in one /// increment from one another. /// [Test] public virtual void TestIncrementingPositions() { Analyzer analyzer = new WhitespaceAnalyzer(); TokenStream ts = analyzer.TokenStream("field", new System.IO.StringReader("one two three four five")); Token reusableToken = new Token(); for (Token nextToken = ts.Next(reusableToken); nextToken != null; nextToken = ts.Next(reusableToken)) { Assert.AreEqual(1, nextToken.GetPositionIncrement(), nextToken.TermText()); } } } }