blob: 29e4f1dd94f781e616271ffbb0596b3b226809d6 [file]
using Lucene.Net.Attributes;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Index.Extensions;
using Lucene.Net.Store;
using Lucene.Net.Util;
using NUnit.Framework;
using System.Collections.Generic;
#nullable enable
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.
*/
/// <summary>
/// Tests that validate the code examples from the package.md documentation.
/// </summary>
[SuppressCodecs("Lucene3x")]
[LuceneNetSpecific]
public class GroupingSearchDocExampleTest : LuceneTestCase
{
/// <summary>
/// Tests the "typical usage for the generic two-pass grouping search" example
/// from the package.md documentation using <see cref="GroupingSearch.ByField(string)"/>.
/// </summary>
[Test]
public void TestFieldGroupingSearchDocExample()
{
Directory dir = NewDirectory();
RandomIndexWriter w = new RandomIndexWriter(
Random,
dir,
NewIndexWriterConfig(TEST_VERSION_CURRENT,
new Analysis.MockAnalyzer(Random)).SetMergePolicy(NewLogMergePolicy()));
// Index some documents with an "author" group field and "content" text field
Document doc = new Document();
doc.Add(new SortedDocValuesField("author", new BytesRef("author1")));
doc.Add(new TextField("author", "author1", Field.Store.YES));
doc.Add(new TextField("content", "random text", Field.Store.YES));
w.AddDocument(doc);
doc = new Document();
doc.Add(new SortedDocValuesField("author", new BytesRef("author1")));
doc.Add(new TextField("author", "author1", Field.Store.YES));
doc.Add(new TextField("content", "more random text", Field.Store.YES));
w.AddDocument(doc);
doc = new Document();
doc.Add(new SortedDocValuesField("author", new BytesRef("author2")));
doc.Add(new TextField("author", "author2", Field.Store.YES));
doc.Add(new TextField("content", "random content", Field.Store.YES));
w.AddDocument(doc);
IndexSearcher indexSearcher = NewSearcher(w.GetReader());
w.Dispose();
// --- Code from package.md documentation ---
Sort groupSort = Sort.RELEVANCE;
const bool fillFields = true;
const bool useCache = true;
const bool requiredTotalGroupCount = true;
const string searchTerm = "random";
const int groupOffset = 0;
const int groupLimit = 10;
FieldGroupingSearch groupingSearch = GroupingSearch.ByField("author");
groupingSearch.SetGroupSort(groupSort);
groupingSearch.SetFillSortFields(fillFields);
if (useCache)
{
// Sets cache in MB
groupingSearch.SetCachingInMB(maxCacheRAMMB: 4.0, cacheScores: true);
}
if (requiredTotalGroupCount)
{
groupingSearch.SetAllGroups(true);
}
TermQuery query = new TermQuery(new Index.Term("content", searchTerm));
TopGroups<BytesRef> result = groupingSearch.Search(indexSearcher, query, groupOffset, groupLimit);
// Verify results
Assert.IsNotNull(result);
assertEquals(3, result.TotalHitCount);
assertEquals(2, result.Groups.Length); // 2 groups: author1 and author2
if (requiredTotalGroupCount)
{
int? totalGroupCount = result.TotalGroupCount;
Assert.IsNotNull(totalGroupCount);
assertEquals(2, totalGroupCount!.Value);
}
indexSearcher.IndexReader.Dispose();
dir.Dispose();
}
/// <summary>
/// Tests the "GroupingSearch convenience utility" example for doc block grouping
/// from the package.md documentation using <see cref="GroupingSearch.ByDocBlock(Filter)"/>.
/// </summary>
[Test]
public void TestDocBlockGroupingSearchDocExample()
{
Directory dir = NewDirectory();
RandomIndexWriter w = new RandomIndexWriter(
Random,
dir,
NewIndexWriterConfig(TEST_VERSION_CURRENT,
new Analysis.MockAnalyzer(Random)).SetMergePolicy(NewLogMergePolicy()));
// --- Indexing code from package.md documentation ---
// Group 1: two documents by author1
List<Document> oneGroup = new List<Document>();
Document doc = new Document();
doc.Add(new TextField("content", "random text", Field.Store.YES));
oneGroup.Add(doc);
doc = new Document();
doc.Add(new TextField("content", "more random text", Field.Store.YES));
oneGroup.Add(doc);
Field groupEndField = new StringField("groupEnd", "x", Field.Store.NO);
oneGroup[oneGroup.Count - 1].Add(groupEndField);
w.AddDocuments(oneGroup);
// Group 2: one document by author2
oneGroup = new List<Document>();
doc = new Document();
doc.Add(new TextField("content", "random content", Field.Store.YES));
oneGroup.Add(doc);
groupEndField = new StringField("groupEnd", "x", Field.Store.NO);
oneGroup[oneGroup.Count - 1].Add(groupEndField);
w.AddDocuments(oneGroup);
IndexSearcher indexSearcher = NewSearcher(w.GetReader());
w.Dispose();
// --- Search code from package.md documentation ---
Sort groupSort = Sort.RELEVANCE;
const bool needsScores = true;
const string searchTerm = "random";
const int groupOffset = 0;
const int groupLimit = 10;
// Set this once in your app & save away for reusing across all queries:
Filter groupEndDocs = new CachingWrapperFilter(new QueryWrapperFilter(new TermQuery(new Index.Term("groupEnd", "x"))));
// Per search:
DocBlockGroupingSearch groupingSearch = GroupingSearch.ByDocBlock(groupEndDocs);
groupingSearch.SetGroupSort(groupSort);
groupingSearch.SetIncludeScores(needsScores);
TermQuery query = new TermQuery(new Index.Term("content", searchTerm));
TopGroups<object?> groupsResult = groupingSearch.Search(indexSearcher, query, groupOffset, groupLimit);
// Verify results
Assert.IsNotNull(groupsResult);
assertEquals(3, groupsResult.TotalHitCount);
assertEquals(2, groupsResult.Groups.Length); // 2 doc block groups
// Note that the groupValue of each GroupDocs will be null
foreach (var group in groupsResult.Groups)
{
assertNull(group.GroupValue);
}
indexSearcher.IndexReader.Dispose();
dir.Dispose();
}
}
}