Разделение файлов индекса Lucene без переиндексации - PullRequest
1 голос
/ 04 сентября 2010

Есть ли способ создать отдельные индексные файлы из одного на основе какого-либо правила без повторной переиндексации документов?

Исходный индекс содержит несохраненные поля, что означает, что я не могу читать документыи добавьте их в целевой индекс.

Один из вариантов, упомянутых в SO, - это клонировать индекс во многие, а затем удалить документы, которые не принадлежат этому индексу.Я ищу лучшее решение.

Ответы [ 2 ]

0 голосов
/ 05 мая 2018

Я нашел этот вопрос первым, когда искал решение своей проблемы, поэтому я оставлю свое решение здесь для будущих поколений.В моем случае мне нужно было разделить мой индекс по определенным линиям, а не произвольно вниз по середине или на трети или что там у вас.Это решение C #, использующее Lucene 3.0.3.

Размер моего приложения превышает 300 ГБ, что становится немного неуправляемым.Каждый документ в индексе связан с одним из заводов-изготовителей, который использует приложение.Нет никаких бизнес-причин, по которым одно предприятие будет когда-либо искать данные другого, поэтому мне нужно было аккуратно разделить индекс по этим линиям.Вот код, который я написал для этого:

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).Так что в моей реальной версии есть некоторый дополнительный код для того, чтобы сделать это растение последним, и вместо того, чтобы разделять его, как другие, он оптимизирует оставшийся индекс (который является просто этим растением), а затем переместит его в новый каталог.

В любом случае, надеюсь, что это поможет кому-то там.

0 голосов
/ 04 сентября 2010

Один из вариантов, упомянутых в SO, - это клонировать индекс во многие, а затем удалить документы, которые не принадлежат этому индексу. Я ищу лучшее решение.

Что не так с этим решением? Это выглядит как очень чистое решение, включающее всего несколько строк кода.

UPDATE:

Что касается сценария, в котором у вас есть индекс 100G, который нужно разделить на 500 раз, попробуйте следующее: для каждого подмножества документов, которые вы хотите вырезать из индекса, создайте жесткие ссылки на исходный индекс, откройте связанный индекс и удалить документы, которые не относятся к этому индексу. Если вы работаете в Linux, жесткую ссылку на каталог можно выполнить:

cp -lrp myindex myindex.copy

Это можно делать столько раз, сколько вам нужно, и ссылки не занимают места на диске.

...