【问题标题】:Split Lucene index files without reindexing拆分 Lucene 索引文件而不重新索引
【发布时间】:2010-09-04 09:03:26
【问题描述】:

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

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

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

【问题讨论】:

    标签: lucene lucene.net


    【解决方案1】:

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

    这个解决方案有什么问题?这让我觉得这是一个非常干净的解决方案,只涉及几行代码。

    更新:

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

    cp -lrp myindex myindex.copy
    

    您可以根据需要多次执行此操作,并且链接不会占用任何磁盘空间。

    【讨论】:

    • 没有错,但是当您的索引为 100Gigs 并且您想将其拆分为 500 个不同的索引时,请考虑这样做。只需根据所需的时间和空间在脑海中运行场景即可。
    【解决方案2】:

    我在寻找我的问题的解决方案时首先发现了这个问题,所以我将把我的解决方案留给后代。就我而言,我需要沿着特定的线分割我的索引,而不是随意地从中间向下或分成三等分或你有什么。这是使用 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/3)。所以在我的真实版本中,有一些额外的代码可以最后做那个植物,而不是像其他的那样将它拆分出来,它将优化剩余的索引(就是那个植物),然后将它移动到它的新目录中。

    无论如何,希望这对那里的人有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多