Это мой первый вопрос о переполнении стека, поэтому желаем мне удачи.Как сохранить индекс Lucene без удаленных документов
Я делаю процесс классификации по индексу Lucene с java, и мне нужно обновить поле документа с именем category. Для этой цели я использовал Lucene 4.2 с функцией updateDocument() для индексатора, и ее работа очень хорошо, за исключением части удаления. Даже если я использую функцию forceMergeDeletes() после обновления, индекс покажет мне некоторые уже удаленные документы. Например, если я запустил классификацию по индексу с 1000 документами, то окончательное количество документов в индексе останется прежним и будет работать так, как ожидалось, но когда я увеличиваю индексные документы до 10000, индекс показывает некоторые уже удаленные документы, но не все. Итак, как я могу удалить эти удаленные документы из индекса?
Вот некоторые фрагменты моего кода:
public static void main(String[] args) throws IOException, ParseException {
///////////////////////Preparing config data////////////////////////////
File indexDir = new File("/indexDir");
Directory fsDir = FSDirectory.open(indexDir);
IndexWriterConfig iwConf = new IndexWriterConfig(Version.LUCENE_42, new WhitespaceSpanishAnalyzer());
iwConf.setOpenMode(IndexWriterConfig.OpenMode.APPEND);
IndexWriter indexWriter = new IndexWriter(fsDir, iwConf);
IndexReader reader = DirectoryReader.open(fsDir);
IndexSearcher indexSearcher = new IndexSearcher(reader);
KNearestNeighborClassifier classifier = new KNearestNeighborClassifier(100);
AtomicReader ar = new SlowCompositeReaderWrapper((CompositeReader) reader);
classifier.train(ar, "text", "category", new WhitespaceSpanishAnalyzer());
System.out.println("***Before***");
showIndexedDocuments(reader);
System.out.println("***Before***");
int maxdoc = reader.maxDoc();
int j = 0;
for (int i = 0; i < maxdoc; i++) {
Document doc = reader.document(i);
String clusterClasif = doc.get("category");
String text = doc.get("text");
String docid = doc.get("doc_id");
ClassificationResult<BytesRef> result = classifier.assignClass(text);
String classified = result.getAssignedClass().utf8ToString();
if (!classified.isEmpty() && clusterClasif.compareTo(classified) != 0) {
Term term = new Term("doc_id", docid);
doc.removeField("category");
doc.add(new StringField("category",
classified, Field.Store.YES));
indexWriter.updateDocument(term,doc);
j++;
}
}
indexWriter.forceMergeDeletes(true);
indexWriter.close();
System.out.println("Classified documents count: " + j);
System.out.println();
reader.close();
reader = DirectoryReader.open(fsDir);
System.out.println("Deleted docs: " + reader.numDeletedDocs());
System.out.println("***After***");
showIndexedDocuments(reader);
}
private static void showIndexedDocuments(IndexReader reader) throws IOException {
int maxdoc = reader.maxDoc();
for (int i = 0; i < maxdoc; i++) {
Document doc = reader.document(i);
String idDoc = doc.get("doc_id");
String text = doc.get("text");
String category = doc.get("category");
System.out.println("Id Doc: " + idDoc);
System.out.println("Category: " + category);
System.out.println("Text: " + text);
System.out.println();
}
System.out.println("Total: " + maxdoc);
}
У меня есть много часов в поисках решения этого, кому-то сказать, что удаленные документы в индексе не важны, и что в конечном счете они будут стираться, когда мы продолжаем добавлять документы к индексу, но мне нужно контролировать этот процесс таким образом, чтобы я мог перебирать индексные документы в любое время и что документы, которые я извлекаю, на самом деле являются живыми. В версиях Lucene, предшествующих версии 4.0, была функция в классе IndexReader с именем isDeleted (docId), которая дает, если документ был отмечен, удаленный, что может быть только половиной решения моей проблемы, но я не нашел способ сделать это с помощью версия 4.2 Lucene. Если вы знаете, как это сделать, я очень благодарен, если вы поделитесь им.
Спасибо за ваш ответ. Руководство Lucene Migration было очень полезно, я тоже буду смотреть на него. – Reinier