将现有Lucene索引拆分为两半的最佳方法是什么,即每个拆分应包含原始索引中文档总数的一半
答案 0 :(得分:3)
拆分现有索引(不重新索引所有文档)的最简单方法是:
这可能不是最有效的方法,但它只需要很少的编码。
答案 1 :(得分:1)
一个相当强大的机制是使用文档的校验和,以索引的数量为模,来决定它将进入哪个索引。
答案 2 :(得分:1)
Lucene的最新版本有一个专门的工具来执行此操作(在contrib / misc下的IndexSplitter
和MultiPassIndexSplitter
。
答案 3 :(得分:0)
这个问题是我在研究这个问题的答案时发现的第一个问题,因此我将这个解决方案留给了后代。在我的情况下,我需要沿着特定的行分割我的索引,而不是任意地在中间或三分之一或你有什么。这是使用Lucene 3.0.3的C#解决方案。
我的应用程序的索引大小超过300GB,这有点难以管理。索引中的每个文档都与使用该应用程序的制造工厂之一相关联。没有商业原因,一家工厂会搜索另一家工厂的数据,所以我需要沿着这些线干净地划分指数。这是我写的代码:
var distinctPlantIDs = databaseRepo.GetDistinctPlantIDs();
var sourceDir = GetOldIndexDir();
foreach (var plantID in distinctPlantIDs)
{
var query = new TermQuery(new Term("PlantID", plantID.ToString()));
var targetDir = GetNewIndexDirForPlant(plantID); //returns a unique directory where this plant's index will go
//read each plant's documents and write them to the new index
using (var analyzer = new StandardAnalyzer(Version.LUCENE_30, CharArraySet.EMPTY_SET))
using (var sourceSearcher = new IndexSearcher(sourceDir, true))
using (var destWriter = new IndexWriter(targetDir, analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED))
{
var numHits = sourceSearcher.DocFreq(query.Term);
if (numHits <= 0) continue;
var hits = sourceSearcher.Search(query, numHits).ScoreDocs;
foreach (var hit in hits)
{
var doc = sourceSearcher.Doc(hit.Doc);
destWriter.AddDocument(doc);
}
destWriter.Optimize();
destWriter.Commit();
}
//delete the documents out of the old index
using (var analyzer = new StandardAnalyzer(Version.LUCENE_30, CharArraySet.EMPTY_SET))
using (var sourceWriter = new IndexWriter(sourceIndexDir, analyzer, false, IndexWriter.MaxFieldLength.UNLIMITED))
{
sourceWriter.DeleteDocuments(query);
sourceWriter.Commit();
}
}
那个从旧索引中删除记录的部分就在那里,因为在我的情况下,一个工厂的记录占据了索引的大部分(超过2 / 3rds)。因此,在我的真实版本中,有一些额外的代码可以最后完成该工厂,而不是像其他工具那样将其拆分,它将优化剩余的索引(这只是工厂),然后将其移动到新目录。
无论如何,希望这可以帮助那些人。