拆分Lucene索引文件而无需重新索引

时间:2010-09-04 09:03:26

标签: lucene lucene.net

有没有办法根据某种规则从单个索引文件生成单独的索引文件,而无需再次重新索引文档?

原始索引包含非存储字段,这意味着我无法读取文档并将其添加到目标索引。

SO中提到的一个选项是将索引克隆为多个,然后删除不属于该索引的文档。我正在寻找更好的解决方案。

2 个答案:

答案 0 :(得分:0)

  

SO中提到的一个选项是将索引克隆为多个,然后删除不属于该索引的文档。我正在寻找更好的解决方案。

这个解决方案有什么问题?这让我感觉非常干净,仅涉及几行代码。

更新:

关于你有100G索引的场景,想要分割500次,试试这个:对于你想要从索引中创建的每个文档子集,创建指向源索引的硬链接,打开链接索引和删除不属于该索引的文档。如果你在Linux上,可以通过以下方式硬链接目录:

cp -lrp myindex myindex.copy

这可以根据需要多次完成,链接不占用任何磁盘空间。

答案 1 :(得分: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)。因此,在我的真实版本中,有一些额外的代码可以最后完成该工厂,而不是像其他工具那样将其拆分,它将优化剩余的索引(这只是工厂),然后将其移动到新目录。

无论如何,希望这可以帮助那些人。