blob: 4a4cde67ddc147419854b6b383d371ef00057825 [file] [log] [blame]
using Lucene.Net.Diagnostics;
using Lucene.Net.Documents;
using NUnit.Framework;
using Assert = Lucene.Net.TestFramework.Assert;
namespace Lucene.Net.Search
{
/*
* 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 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 IndexReader = Lucene.Net.Index.IndexReader;
using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
using Term = Lucene.Net.Index.Term;
/// <summary>
/// this class only tests some basic functionality in CSQ, the main parts are mostly
/// tested by MultiTermQuery tests, explanations seems to be tested in TestExplanations!
/// </summary>
[TestFixture]
public class TestConstantScoreQuery : LuceneTestCase
{
[Test]
public virtual void TestCSQ()
{
Query q1 = new ConstantScoreQuery(new TermQuery(new Term("a", "b")));
Query q2 = new ConstantScoreQuery(new TermQuery(new Term("a", "c")));
Query q3 = new ConstantScoreQuery(TermRangeFilter.NewStringRange("a", "b", "c", true, true));
QueryUtils.Check(q1);
QueryUtils.Check(q2);
QueryUtils.CheckEqual(q1, q1);
QueryUtils.CheckEqual(q2, q2);
QueryUtils.CheckEqual(q3, q3);
QueryUtils.CheckUnequal(q1, q2);
QueryUtils.CheckUnequal(q2, q3);
QueryUtils.CheckUnequal(q1, q3);
QueryUtils.CheckUnequal(q1, new TermQuery(new Term("a", "b")));
}
private void CheckHits(IndexSearcher searcher, Query q, float expectedScore, string scorerClassName, string innerScorerClassName)
{
int[] count = new int[1];
searcher.Search(q, new CollectorAnonymousClass(this, expectedScore, scorerClassName, innerScorerClassName, count));
Assert.AreEqual(1, count[0], "invalid number of results");
}
private class CollectorAnonymousClass : ICollector
{
private readonly TestConstantScoreQuery outerInstance;
private readonly float expectedScore;
private readonly string scorerClassName;
private readonly string innerScorerClassName;
private readonly int[] count;
public CollectorAnonymousClass(TestConstantScoreQuery outerInstance, float expectedScore, string scorerClassName, string innerScorerClassName, int[] count)
{
this.outerInstance = outerInstance;
this.expectedScore = expectedScore;
this.scorerClassName = scorerClassName;
this.innerScorerClassName = innerScorerClassName;
this.count = count;
}
private Scorer scorer;
public virtual void SetScorer(Scorer scorer)
{
this.scorer = scorer;
Assert.AreEqual(scorerClassName, scorer.GetType().Name, "Scorer is implemented by wrong class");
if (innerScorerClassName != null && scorer is ConstantScoreQuery.ConstantScorer)
{
ConstantScoreQuery.ConstantScorer innerScorer = (ConstantScoreQuery.ConstantScorer)scorer;
Assert.AreEqual(innerScorerClassName, innerScorer.docIdSetIterator.GetType().Name, "inner Scorer is implemented by wrong class");
}
}
public virtual void Collect(int doc)
{
Assert.AreEqual(expectedScore, this.scorer.GetScore(), 0, "Score differs from expected");
count[0]++;
}
public virtual void SetNextReader(AtomicReaderContext context)
{
}
public virtual bool AcceptsDocsOutOfOrder => true;
}
[Test]
public virtual void TestWrapped2Times()
{
Directory directory = null;
IndexReader reader = null;
IndexSearcher searcher = null;
try
{
directory = NewDirectory();
RandomIndexWriter writer = new RandomIndexWriter(
#if FEATURE_INSTANCE_TESTDATA_INITIALIZATION
this,
#endif
Random, directory);
Document doc = new Document();
doc.Add(NewStringField("field", "term", Field.Store.NO));
writer.AddDocument(doc);
reader = writer.GetReader();
writer.Dispose();
// we don't wrap with AssertingIndexSearcher in order to have the original scorer in setScorer.
searcher = NewSearcher(reader, true, false);
// set a similarity that does not normalize our boost away
searcher.Similarity = new DefaultSimilarityAnonymousClass(this);
Query csq1 = new ConstantScoreQuery(new TermQuery(new Term("field", "term")));
csq1.Boost = 2.0f;
Query csq2 = new ConstantScoreQuery(csq1);
csq2.Boost = 5.0f;
BooleanQuery bq = new BooleanQuery();
bq.Add(csq1, Occur.SHOULD);
bq.Add(csq2, Occur.SHOULD);
Query csqbq = new ConstantScoreQuery(bq);
csqbq.Boost = 17.0f;
CheckHits(searcher, csq1, csq1.Boost, typeof(ConstantScoreQuery.ConstantScorer).Name, null);
CheckHits(searcher, csq2, csq2.Boost, typeof(ConstantScoreQuery.ConstantScorer).Name, typeof(ConstantScoreQuery.ConstantScorer).Name);
// for the combined BQ, the scorer should always be BooleanScorer's BucketScorer, because our scorer supports out-of order collection!
string bucketScorerClass = typeof(FakeScorer).Name;
CheckHits(searcher, bq, csq1.Boost + csq2.Boost, bucketScorerClass, null);
CheckHits(searcher, csqbq, csqbq.Boost, typeof(ConstantScoreQuery.ConstantScorer).Name, bucketScorerClass);
}
finally
{
if (reader != null)
{
reader.Dispose();
}
if (directory != null)
{
directory.Dispose();
}
}
}
private class DefaultSimilarityAnonymousClass : DefaultSimilarity
{
private readonly TestConstantScoreQuery outerInstance;
public DefaultSimilarityAnonymousClass(TestConstantScoreQuery outerInstance)
{
this.outerInstance = outerInstance;
}
public override float QueryNorm(float sumOfSquaredWeights)
{
return 1.0f;
}
}
[Test]
public virtual void TestConstantScoreQueryAndFilter()
{
Directory d = NewDirectory();
RandomIndexWriter w = new RandomIndexWriter(
#if FEATURE_INSTANCE_TESTDATA_INITIALIZATION
this,
#endif
Random, d);
Document doc = new Document();
doc.Add(NewStringField("field", "a", Field.Store.NO));
w.AddDocument(doc);
doc = new Document();
doc.Add(NewStringField("field", "b", Field.Store.NO));
w.AddDocument(doc);
IndexReader r = w.GetReader();
w.Dispose();
Filter filterB = new CachingWrapperFilter(new QueryWrapperFilter(new TermQuery(new Term("field", "b"))));
Query query = new ConstantScoreQuery(filterB);
IndexSearcher s = NewSearcher(r);
Assert.AreEqual(1, s.Search(query, filterB, 1).TotalHits); // Query for field:b, Filter field:b
Filter filterA = new CachingWrapperFilter(new QueryWrapperFilter(new TermQuery(new Term("field", "a"))));
query = new ConstantScoreQuery(filterA);
Assert.AreEqual(0, s.Search(query, filterB, 1).TotalHits); // Query field:b, Filter field:a
r.Dispose();
d.Dispose();
}
// LUCENE-5307
// don't reuse the scorer of filters since they have been created with bulkScorer=false
[Test]
public virtual void TestQueryWrapperFilter()
{
Directory d = NewDirectory();
RandomIndexWriter w = new RandomIndexWriter(
#if FEATURE_INSTANCE_TESTDATA_INITIALIZATION
this,
#endif
Random, d);
Document doc = new Document();
doc.Add(NewStringField("field", "a", Field.Store.NO));
w.AddDocument(doc);
IndexReader r = w.GetReader();
w.Dispose();
Filter filter = new QueryWrapperFilter(AssertingQuery.Wrap(Random, new TermQuery(new Term("field", "a"))));
IndexSearcher s = NewSearcher(r);
if (Debugging.AssertsEnabled) Debugging.Assert(s is AssertingIndexSearcher);
// this used to fail
s.Search(new ConstantScoreQuery(filter), new TotalHitCountCollector());
// check the rewrite
Query rewritten = (new ConstantScoreQuery(filter)).Rewrite(r);
Assert.IsTrue(rewritten is ConstantScoreQuery);
Assert.IsTrue(((ConstantScoreQuery)rewritten).Query is AssertingQuery);
r.Dispose();
d.Dispose();
}
}
}