|  | using System; | 
|  | using Lucene.Net.Documents; | 
|  | using Lucene.Net.Index; | 
|  | using Lucene.Net.Queries.Function.ValueSources; | 
|  | using Lucene.Net.Search; | 
|  | using Lucene.Net.Store; | 
|  | using Lucene.Net.Util; | 
|  | using NUnit.Framework; | 
|  |  | 
|  | namespace Lucene.Net.Tests.Queries.Function | 
|  | { | 
|  | /// <summary> | 
|  | /// Test that functionquery's getSortField() actually works. | 
|  | /// </summary> | 
|  | public class TestFunctionQuerySort : LuceneTestCase | 
|  | { | 
|  | [Test] | 
|  | public void TestSearchAfterWhenSortingByFunctionValues() | 
|  | { | 
|  | Directory dir = NewDirectory(); | 
|  | IndexWriterConfig iwc = NewIndexWriterConfig(TEST_VERSION_CURRENT, null); | 
|  | iwc.SetMergePolicy(NewLogMergePolicy()); // depends on docid order | 
|  | RandomIndexWriter writer = new RandomIndexWriter(Random(), dir, iwc); | 
|  |  | 
|  | Document doc = new Document(); | 
|  | Field field = new StringField("value", "", Field.Store.YES); | 
|  | doc.Add(field); | 
|  |  | 
|  | // Save docs unsorted (decreasing value n, n-1, ...) | 
|  | const int NUM_VALS = 5; | 
|  | for (int val = NUM_VALS; val > 0; val--) | 
|  | { | 
|  | field.StringValue = Convert.ToString(val); | 
|  | writer.AddDocument(doc); | 
|  | } | 
|  |  | 
|  | // Open index | 
|  | IndexReader reader = writer.Reader; | 
|  | writer.Dispose(); | 
|  | IndexSearcher searcher = NewSearcher(reader); | 
|  |  | 
|  | // Get ValueSource from FieldCache | 
|  | IntFieldSource src = new IntFieldSource("value"); | 
|  | // ...and make it a sort criterion | 
|  | SortField sf = src.GetSortField(false).Rewrite(searcher); | 
|  | Sort orderBy = new Sort(sf); | 
|  |  | 
|  | // Get hits sorted by our FunctionValues (ascending values) | 
|  | Query q = new MatchAllDocsQuery(); | 
|  | TopDocs hits = searcher.Search(q, reader.MaxDoc, orderBy); | 
|  | assertEquals(NUM_VALS, hits.ScoreDocs.Length); | 
|  | // Verify that sorting works in general | 
|  | int i = 0; | 
|  | foreach (ScoreDoc hit in hits.ScoreDocs) | 
|  | { | 
|  | int valueFromDoc = Convert.ToInt32(reader.Document(hit.Doc).Get("value")); | 
|  | assertEquals(++i, valueFromDoc); | 
|  | } | 
|  |  | 
|  | // Now get hits after hit #2 using IS.searchAfter() | 
|  | int afterIdx = 1; | 
|  | FieldDoc afterHit = (FieldDoc)hits.ScoreDocs[afterIdx]; | 
|  | hits = searcher.SearchAfter(afterHit, q, reader.MaxDoc, orderBy); | 
|  |  | 
|  | // Expected # of hits: NUM_VALS - 2 | 
|  | assertEquals(NUM_VALS - (afterIdx + 1), hits.ScoreDocs.Length); | 
|  |  | 
|  | // Verify that hits are actually "after" | 
|  | int afterValue = (int)((double?)afterHit.Fields[0]); | 
|  | foreach (ScoreDoc hit in hits.ScoreDocs) | 
|  | { | 
|  | int val = Convert.ToInt32(reader.Document(hit.Doc).Get("value")); | 
|  | assertTrue(afterValue <= val); | 
|  | assertFalse(hit.Doc == afterHit.Doc); | 
|  | } | 
|  | reader.Dispose(); | 
|  | dir.Dispose(); | 
|  | } | 
|  | } | 
|  | } |