有没有办法根据某种规则从单个索引文件生成单独的索引文件,而无需再次重新索引文档?
原始索引包含非存储字段,这意味着我无法读取文档并将其添加到目标索引。
SO中提到的一个选项是将索引克隆为多个,然后删除不属于该索引的文档。我正在寻找更好的解决方案。
答案 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)。因此,在我的真实版本中,有一些额外的代码可以最后完成该工厂,而不是像其他工具那样将其拆分,它将优化剩余的索引(这只是工厂),然后将其移动到新目录。
无论如何,希望这可以帮助那些人。