| using Lucene.Net.Analysis; |
| using Lucene.Net.Documents; |
| using Lucene.Net.Index; |
| using Lucene.Net.Index.Extensions; |
| using Lucene.Net.Queries.Function; |
| using Lucene.Net.Queries.Function.ValueSources; |
| using Lucene.Net.Store; |
| using Lucene.Net.Util; |
| using Lucene.Net.Util.Mutable; |
| using NUnit.Framework; |
| using System; |
| using System.Collections; |
| using System.Collections.Generic; |
| using System.Reflection; |
| |
| namespace Lucene.Net.Search.Grouping |
| { |
| /* |
| * 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. |
| */ |
| |
| public class GroupingSearchTest : LuceneTestCase |
| { |
| // Tests some very basic usages... |
| [Test] |
| public virtual void TestBasic() |
| { |
| |
| string groupField = "author"; |
| |
| FieldType customType = new FieldType(); |
| customType.IsStored = (true); |
| |
| Directory dir = NewDirectory(); |
| RandomIndexWriter w = new RandomIndexWriter( |
| Random, |
| dir, |
| NewIndexWriterConfig(TEST_VERSION_CURRENT, |
| new MockAnalyzer(Random)).SetMergePolicy(NewLogMergePolicy())); |
| bool canUseIDV = !"Lucene3x".Equals(w.IndexWriter.Config.Codec.Name, StringComparison.Ordinal); |
| List<Document> documents = new List<Document>(); |
| // 0 |
| Document doc = new Document(); |
| AddGroupField(doc, groupField, "author1", canUseIDV); |
| doc.Add(new TextField("content", "random text", Field.Store.YES)); |
| doc.Add(new Field("id", "1", customType)); |
| documents.Add(doc); |
| |
| // 1 |
| doc = new Document(); |
| AddGroupField(doc, groupField, "author1", canUseIDV); |
| doc.Add(new TextField("content", "some more random text", Field.Store.YES)); |
| doc.Add(new Field("id", "2", customType)); |
| documents.Add(doc); |
| |
| // 2 |
| doc = new Document(); |
| AddGroupField(doc, groupField, "author1", canUseIDV); |
| doc.Add(new TextField("content", "some more random textual data", Field.Store.YES)); |
| doc.Add(new Field("id", "3", customType)); |
| doc.Add(new StringField("groupend", "x", Field.Store.NO)); |
| documents.Add(doc); |
| w.AddDocuments(documents); |
| documents.Clear(); |
| |
| // 3 |
| doc = new Document(); |
| AddGroupField(doc, groupField, "author2", canUseIDV); |
| doc.Add(new TextField("content", "some random text", Field.Store.YES)); |
| doc.Add(new Field("id", "4", customType)); |
| doc.Add(new StringField("groupend", "x", Field.Store.NO)); |
| w.AddDocument(doc); |
| |
| // 4 |
| doc = new Document(); |
| AddGroupField(doc, groupField, "author3", canUseIDV); |
| doc.Add(new TextField("content", "some more random text", Field.Store.YES)); |
| doc.Add(new Field("id", "5", customType)); |
| documents.Add(doc); |
| |
| // 5 |
| doc = new Document(); |
| AddGroupField(doc, groupField, "author3", canUseIDV); |
| doc.Add(new TextField("content", "random", Field.Store.YES)); |
| doc.Add(new Field("id", "6", customType)); |
| doc.Add(new StringField("groupend", "x", Field.Store.NO)); |
| documents.Add(doc); |
| w.AddDocuments(documents); |
| documents.Clear(); |
| |
| // 6 -- no author field |
| doc = new Document(); |
| doc.Add(new TextField("content", "random word stuck in alot of other text", Field.Store.YES)); |
| doc.Add(new Field("id", "6", customType)); |
| doc.Add(new StringField("groupend", "x", Field.Store.NO)); |
| |
| w.AddDocument(doc); |
| |
| IndexSearcher indexSearcher = NewSearcher(w.GetReader()); |
| w.Dispose(); |
| |
| Sort groupSort = Sort.RELEVANCE; |
| GroupingSearch groupingSearch = CreateRandomGroupingSearch(groupField, groupSort, 5, canUseIDV); |
| |
| ITopGroups<object> groups = groupingSearch.Search(indexSearcher, (Filter)null, new TermQuery(new Index.Term("content", "random")), 0, 10); |
| |
| assertEquals(7, groups.TotalHitCount); |
| assertEquals(7, groups.TotalGroupedHitCount); |
| assertEquals(4, groups.Groups.Length); |
| |
| // relevance order: 5, 0, 3, 4, 1, 2, 6 |
| |
| // the later a document is added the higher this docId |
| // value |
| IGroupDocs<object> group = groups.Groups[0]; |
| CompareGroupValue("author3", group); |
| assertEquals(2, group.ScoreDocs.Length); |
| assertEquals(5, group.ScoreDocs[0].Doc); |
| assertEquals(4, group.ScoreDocs[1].Doc); |
| assertTrue(group.ScoreDocs[0].Score > group.ScoreDocs[1].Score); |
| |
| group = groups.Groups[1]; |
| CompareGroupValue("author1", group); |
| assertEquals(3, group.ScoreDocs.Length); |
| assertEquals(0, group.ScoreDocs[0].Doc); |
| assertEquals(1, group.ScoreDocs[1].Doc); |
| assertEquals(2, group.ScoreDocs[2].Doc); |
| assertTrue(group.ScoreDocs[0].Score > group.ScoreDocs[1].Score); |
| assertTrue(group.ScoreDocs[1].Score > group.ScoreDocs[2].Score); |
| |
| group = groups.Groups[2]; |
| CompareGroupValue("author2", group); |
| assertEquals(1, group.ScoreDocs.Length); |
| assertEquals(3, group.ScoreDocs[0].Doc); |
| |
| group = groups.Groups[3]; |
| CompareGroupValue(null, group); |
| assertEquals(1, group.ScoreDocs.Length); |
| assertEquals(6, group.ScoreDocs[0].Doc); |
| |
| Filter lastDocInBlock = new CachingWrapperFilter(new QueryWrapperFilter(new TermQuery(new Index.Term("groupend", "x")))); |
| groupingSearch = new GroupingSearch(lastDocInBlock); |
| groups = groupingSearch.Search(indexSearcher, null, new TermQuery(new Index.Term("content", "random")), 0, 10); |
| |
| assertEquals(7, groups.TotalHitCount); |
| assertEquals(7, groups.TotalGroupedHitCount); |
| assertEquals(4, groups.TotalGroupCount.GetValueOrDefault()); |
| assertEquals(4, groups.Groups.Length); |
| |
| indexSearcher.IndexReader.Dispose(); |
| dir.Dispose(); |
| } |
| |
| private void AddGroupField(Document doc, string groupField, string value, bool canUseIDV) |
| { |
| doc.Add(new TextField(groupField, value, Field.Store.YES)); |
| if (canUseIDV) |
| { |
| doc.Add(new SortedDocValuesField(groupField, new BytesRef(value))); |
| } |
| } |
| |
| private void CompareGroupValue(string expected, IGroupDocs<object> group) |
| { |
| if (expected == null) |
| { |
| if (group.GroupValue == null) |
| { |
| return; |
| } |
| else if (group.GroupValue.GetType().IsAssignableFrom(typeof(MutableValueStr))) |
| { |
| return; |
| } |
| else if (((BytesRef)group.GroupValue).Length == 0) |
| { |
| return; |
| } |
| fail(); |
| } |
| |
| if (group.GroupValue.GetType().IsAssignableFrom(typeof(BytesRef))) |
| { |
| assertEquals(new BytesRef(expected), group.GroupValue); |
| } |
| else if (group.GroupValue.GetType().IsAssignableFrom(typeof(MutableValueStr))) |
| { |
| MutableValueStr v = new MutableValueStr(); |
| v.Value = new BytesRef(expected); |
| assertEquals(v, group.GroupValue); |
| } |
| else |
| { |
| fail(); |
| } |
| } |
| |
| private GroupingSearch CreateRandomGroupingSearch(string groupField, Sort groupSort, int docsInGroup, bool canUseIDV) |
| { |
| GroupingSearch groupingSearch; |
| if (Random.nextBoolean()) |
| { |
| ValueSource vs = new BytesRefFieldSource(groupField); |
| groupingSearch = new GroupingSearch(vs, new Hashtable()); |
| } |
| else |
| { |
| groupingSearch = new GroupingSearch(groupField); |
| } |
| |
| groupingSearch.SetGroupSort(groupSort); |
| groupingSearch.SetGroupDocsLimit(docsInGroup); |
| |
| if (Random.nextBoolean()) |
| { |
| groupingSearch.SetCachingInMB(4.0, true); |
| } |
| |
| return groupingSearch; |
| } |
| |
| [Test] |
| public virtual void TestSetAllGroups() |
| { |
| Directory dir = NewDirectory(); |
| RandomIndexWriter w = new RandomIndexWriter( |
| Random, |
| dir, |
| NewIndexWriterConfig(TEST_VERSION_CURRENT, |
| new MockAnalyzer(Random)).SetMergePolicy(NewLogMergePolicy())); |
| Document doc = new Document(); |
| doc.Add(NewField("group", "foo", StringField.TYPE_NOT_STORED)); |
| w.AddDocument(doc); |
| |
| IndexSearcher indexSearcher = NewSearcher(w.GetReader()); |
| w.Dispose(); |
| |
| GroupingSearch gs = new GroupingSearch("group"); |
| gs.SetAllGroups(true); |
| ITopGroups<object> groups = gs.Search(indexSearcher, null, new TermQuery(new Index.Term("group", "foo")), 0, 10); |
| assertEquals(1, groups.TotalHitCount); |
| //assertEquals(1, groups.totalGroupCount.intValue()); |
| assertEquals(1, groups.TotalGroupedHitCount); |
| assertEquals(1, gs.GetAllMatchingGroups().Count); |
| indexSearcher.IndexReader.Dispose(); |
| dir.Dispose(); |
| } |
| } |
| } |