| /* |
| * 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. |
| */ |
| package org.apache.lucene.queries.function; |
| |
| import java.util.Arrays; |
| import java.util.List; |
| |
| import org.apache.lucene.analysis.Analyzer; |
| import org.apache.lucene.analysis.MockAnalyzer; |
| import org.apache.lucene.document.Document; |
| import org.apache.lucene.document.Field; |
| import org.apache.lucene.document.SortedDocValuesField; |
| import org.apache.lucene.document.StringField; |
| import org.apache.lucene.document.TextField; |
| import org.apache.lucene.index.IndexReader; |
| import org.apache.lucene.index.IndexWriterConfig; |
| import org.apache.lucene.index.LeafReaderContext; |
| import org.apache.lucene.index.RandomIndexWriter; |
| import org.apache.lucene.index.Term; |
| import org.apache.lucene.search.CheckHits; |
| import org.apache.lucene.search.DoubleValuesSource; |
| import org.apache.lucene.search.IndexSearcher; |
| import org.apache.lucene.search.LongValuesSource; |
| import org.apache.lucene.search.MatchAllDocsQuery; |
| import org.apache.lucene.search.Query; |
| import org.apache.lucene.search.ScoreDoc; |
| import org.apache.lucene.search.ScoreMode; |
| import org.apache.lucene.search.Sort; |
| import org.apache.lucene.search.SortField; |
| import org.apache.lucene.search.TopDocs; |
| import org.apache.lucene.search.Weight; |
| import org.apache.lucene.store.Directory; |
| import org.apache.lucene.util.BytesRef; |
| import org.apache.lucene.util.IOUtils; |
| import org.apache.lucene.util.LuceneTestCase; |
| import org.junit.AfterClass; |
| import org.junit.BeforeClass; |
| |
| public class TestIndexReaderFunctions extends LuceneTestCase { |
| |
| static Directory dir; |
| static Analyzer analyzer; |
| static IndexReader reader; |
| static IndexSearcher searcher; |
| |
| static final List<String[]> documents = Arrays.asList( |
| /* id, double, float, int, long, string, text, double MV (x3), int MV (x3)*/ |
| new String[] { "0", "3.63", "5.2", "35", "4343", "test", "this is a test test test", "2.13", "3.69", "-0.11", "1", "7", "5"}, |
| new String[] { "1", "5.65", "9.3", "54", "1954", "bar", "second test", "12.79", "123.456", "0.01", "12", "900", "-1" }); |
| |
| @BeforeClass |
| public static void beforeClass() throws Exception { |
| dir = newDirectory(); |
| analyzer = new MockAnalyzer(random()); |
| IndexWriterConfig iwConfig = newIndexWriterConfig(analyzer); |
| iwConfig.setMergePolicy(newLogMergePolicy()); |
| RandomIndexWriter iw = new RandomIndexWriter(random(), dir, iwConfig); |
| for (String [] doc : documents) { |
| Document document = new Document(); |
| document.add(new StringField("id", doc[0], Field.Store.NO)); |
| document.add(new SortedDocValuesField("id", new BytesRef(doc[0]))); |
| document.add(new StringField("string", doc[5], Field.Store.NO)); |
| document.add(new SortedDocValuesField("string", new BytesRef(doc[5]))); |
| document.add(new TextField("text", doc[6], Field.Store.NO)); |
| iw.addDocument(document); |
| } |
| |
| reader = iw.getReader(); |
| searcher = newSearcher(reader); |
| iw.close(); |
| } |
| |
| @AfterClass |
| public static void afterClass() throws Exception { |
| IOUtils.close(reader, dir, analyzer); |
| searcher = null; |
| reader = null; |
| dir = null; |
| analyzer = null; |
| } |
| |
| public void testDocFreq() throws Exception { |
| DoubleValuesSource vs = IndexReaderFunctions.docFreq(new Term("text", "test")); |
| assertHits(vs, new float[] { 2f, 2f }); |
| assertEquals("docFreq(text:test)", vs.toString()); |
| assertCacheable(vs, false); |
| } |
| |
| public void testMaxDoc() throws Exception { |
| DoubleValuesSource vs = IndexReaderFunctions.maxDoc(); |
| assertHits(vs, new float[] { 2f, 2f }); |
| assertEquals("maxDoc()", vs.toString()); |
| assertCacheable(vs, false); |
| } |
| |
| public void testNumDocs() throws Exception { |
| DoubleValuesSource vs = IndexReaderFunctions.numDocs(); |
| assertHits(vs, new float[] { 2f, 2f }); |
| assertEquals("numDocs()", vs.toString()); |
| assertCacheable(vs, false); |
| } |
| |
| public void testSumTotalTermFreq() throws Exception { |
| LongValuesSource vs = IndexReaderFunctions.sumTotalTermFreq("text"); |
| assertHits(vs.toDoubleValuesSource(), new float[] { 8f, 8f }); |
| assertEquals("sumTotalTermFreq(text)", vs.toString()); |
| assertCacheable(vs, false); |
| } |
| |
| public void testTermFreq() throws Exception { |
| assertHits(IndexReaderFunctions.termFreq(new Term("string", "bar")), new float[] { 0f, 1f }); |
| assertHits(IndexReaderFunctions.termFreq(new Term("text", "test")), new float[] { 3f, 1f }); |
| assertHits(IndexReaderFunctions.termFreq(new Term("bogus", "bogus")), new float[] { 0F, 0F }); |
| assertEquals("termFreq(string:bar)", IndexReaderFunctions.termFreq(new Term("string", "bar")).toString()); |
| assertCacheable(IndexReaderFunctions.termFreq(new Term("text", "test")), true); |
| } |
| |
| public void testTotalTermFreq() throws Exception { |
| DoubleValuesSource vs = IndexReaderFunctions.totalTermFreq(new Term("text", "test")); |
| assertHits(vs, new float[] { 4f, 4f }); |
| assertEquals("totalTermFreq(text:test)", vs.toString()); |
| assertCacheable(vs, false); |
| } |
| |
| public void testNumDeletedDocs() throws Exception { |
| DoubleValuesSource vs = IndexReaderFunctions.numDeletedDocs(); |
| assertHits(vs, new float[] { 0, 0 }); |
| assertEquals("numDeletedDocs()", vs.toString()); |
| assertCacheable(vs, false); |
| } |
| |
| public void testSumDocFreq() throws Exception { |
| DoubleValuesSource vs = IndexReaderFunctions.sumDocFreq("text"); |
| assertHits(vs, new float[] { 6, 6 }); |
| assertEquals("sumDocFreq(text)", vs.toString()); |
| assertCacheable(vs, false); |
| } |
| |
| public void testDocCount() throws Exception { |
| DoubleValuesSource vs = IndexReaderFunctions.docCount("text"); |
| assertHits(vs, new float[] { 2, 2 }); |
| assertEquals("docCount(text)", vs.toString()); |
| assertCacheable(vs, false); |
| } |
| |
| void assertCacheable(DoubleValuesSource vs, boolean expected) throws Exception { |
| Query q = new FunctionScoreQuery(new MatchAllDocsQuery(), vs); |
| Weight w = searcher.createWeight(q, ScoreMode.COMPLETE, 1); |
| LeafReaderContext ctx = reader.leaves().get(0); |
| assertEquals(expected, w.isCacheable(ctx)); |
| } |
| |
| void assertCacheable(LongValuesSource vs, boolean expected) throws Exception { |
| Query q = new FunctionScoreQuery(new MatchAllDocsQuery(), vs.toDoubleValuesSource()); |
| Weight w = searcher.createWeight(q, ScoreMode.COMPLETE, 1); |
| LeafReaderContext ctx = reader.leaves().get(0); |
| assertEquals(expected, w.isCacheable(ctx)); |
| } |
| |
| void assertHits(DoubleValuesSource vs, float scores[]) throws Exception { |
| Query q = new FunctionScoreQuery(new MatchAllDocsQuery(), vs); |
| ScoreDoc expected[] = new ScoreDoc[scores.length]; |
| int expectedDocs[] = new int[scores.length]; |
| for (int i = 0; i < expected.length; i++) { |
| expectedDocs[i] = i; |
| expected[i] = new ScoreDoc(i, scores[i]); |
| } |
| TopDocs docs = searcher.search(q, documents.size(), |
| new Sort(new SortField("id", SortField.Type.STRING)), true); |
| CheckHits.checkHits(random(), q, "", searcher, expectedDocs); |
| CheckHits.checkHitsQuery(q, expected, docs.scoreDocs, expectedDocs); |
| CheckHits.checkExplanations(q, "", searcher); |
| assertSort(vs, expected); |
| } |
| |
| void assertSort(DoubleValuesSource vs, ScoreDoc expected[]) throws Exception { |
| boolean reversed = random().nextBoolean(); |
| Arrays.sort(expected, (a, b) -> reversed ? (int) (b.score - a.score) : (int) (a.score - b.score)); |
| int[] expectedDocs = new int[expected.length]; |
| for (int i = 0; i < expected.length; i++) { |
| expectedDocs[i] = expected[i].doc; |
| } |
| TopDocs docs = searcher.search(new MatchAllDocsQuery(), expected.length, |
| new Sort(vs.getSortField(reversed))); |
| CheckHits.checkHitsQuery(new MatchAllDocsQuery(), expected, docs.scoreDocs, expectedDocs); |
| } |
| |
| } |