【问题标题】:How to delete or Update the Documents in apache Lucene如何删除或更新 apache Lucene 中的文档
【发布时间】:2016-09-02 12:52:00
【问题描述】:

目前我能够将文档列表以及单个文档添加到 apache lucene 索引中。但是我在从索引更新文档时遇到了问题:

我的方法是在文件上传后立即进行,因此在写入磁盘之前,我会检查驱动器/文件夹中是否存在文件并根据文件名删除索引。

其次,我将上传的文件添加到 Lucene 索引中。

但我遇到的问题是新添加的文档和旧文档都以不同的内容显示在搜索结果中。

例如:文件名为 Sample_One.txt,带有文本:

这是第一次的示例文本。

从索引中删除上述文件,然后将新的文件内容添加到索引中。

现在文件内容已更新为具有相同文件名的另一个文本:

这是更新内容的示例文本。

在搜索诸如 "sample" 之类的文本时,结果是两次显示 Sample_One.txt 文件,其中包含旧内容和新内容。

我想知道我是否遗漏了什么以及如何将文档更新/删除到索引中。

代码片段是:

//Deleting the Document from the Index
public void deleteDocumentsFromIndexUsingTerm(Document doc) throws IOException, ParseException {
    Term fileTerm = new Term("file_name",doc.get("file_name"));
    Term contentTerm = new Term("content", doc.get("content"));
    Term docIDTerm = new Term("document_id", doc.get("document_id"));

    File indexDir = new File(INDEX_DIRECTORY);

    Directory directory = FSDirectory.open(indexDir.toPath());

    Analyzer analyzer = new StandardAnalyzer();
    IndexWriterConfig conf = new IndexWriterConfig(analyzer);
    IndexWriter indexWriter = new IndexWriter(directory, conf);

    System.out.println("Deleting the term with - "+doc.get("file_name"));
    System.out.println("Deleting the term with contents - "+doc.get("content"));

    indexWriter.deleteDocuments(fileTerm);
    indexWriter.deleteDocuments(contentTerm);
    indexWriter.deleteDocuments(docIDTerm);
    indexWriter.commit();
    indexWriter.close();
}

// 将文档添加到索引的片段

final String INDEX_DIRECTORY = "D:\\Development\\Lucene_Indexer";
    long startTime = System.currentTimeMillis();
    List<ContentHandler> contentHandlerList = new ArrayList<ContentHandler>();

    String fileNames = (String)request.getAttribute("message");

    File file = new File("D:\\Development\\Resume_Sample\\"+fileNames);

    ArrayList<File> fileList = new ArrayList<File>();
    fileList.add(file);

    Metadata metadata = new Metadata();

    // BodyContentHandler set the value as -1 to evade the Text Limit Exception
    ContentHandler handler = new BodyContentHandler(-1);
    ParseContext context = new ParseContext();
    Parser parser = new AutoDetectParser();
    InputStream stream = new FileInputStream(file);

    try {
        parser.parse(stream, handler, metadata, context);
        contentHandlerList.add(handler);
    }catch (TikaException e) {
        e.printStackTrace();
    }catch (SAXException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    finally {
        try {
            stream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    FieldType fieldType = new FieldType();
    fieldType.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS);
    fieldType.setStoreTermVectors(true);
    fieldType.setStoreTermVectorPositions(true);
    fieldType.setStoreTermVectorPayloads(true);
    fieldType.setStoreTermVectorOffsets(true);
    fieldType.setStored(true);


    Analyzer analyzer = new StandardAnalyzer();
    Directory directory = FSDirectory.open(new File(INDEX_DIRECTORY).toPath());
    IndexWriterConfig conf = new IndexWriterConfig(analyzer);
    IndexWriter writer = new IndexWriter(directory, conf);

    Iterator<ContentHandler> handlerIterator = contentHandlerList.iterator();
    Iterator<File> fileIterator = fileList.iterator();

while (handlerIterator.hasNext() && fileIterator.hasNext()) {
    Document doc = new Document();

    String text = handlerIterator.next().toString();
    String textFileName = fileIterator.next().getName();

    String idOne = UUID.randomUUID().toString();

    Field idField = new Field("document_id",idOne,fieldType);
    Field fileNameField = new Field("file_name", textFileName, fieldType);
    Field contentField = new Field("content",text,fieldType);


    doc.add(idField);
    doc.add(contentField);
    doc.add(fileNameField);

    writer.addDocument(doc);

    analyzer.close();
}

writer.commit();
writer.deleteUnusedFiles();
long endTime = System.currentTimeMillis();

writer.close();

首先,我会在文件上传后立即删除文档,然后为更新的文档编制索引。

【问题讨论】:

    标签: java lucene full-text-search


    【解决方案1】:

    问题是您的字段在编入索引时正在被分析,但您尝试删除的术语没有被分析

    最好的解决方案是将要用作此目的的标识符的任何字段设置为StringField,这将导致对其进行索引而不进行分析。如:

    Field idField = new StringField("document_id", idOne);
    doc.add(idField);
    

    或者,您可以使用IndexWriter.deleteDocuments(Query...),并传入分析过的查询(由 QueryParser 生成),但在这种情况下,您应该注意不要删除比您预期更多的文档(任何 查询找到的文档将被删除,而不仅仅是最好的结果)。

    【讨论】:

    • 效果很好。您的建议第二次对我有用,非常有用。
    • 您好,请您帮我解决另一个关于 lucene 中的 AutoSuggestion 的主题。问题stackoverflow链接是:stackoverflow.com/questions/39320279/…
    • 2021 年,Lucene 8.9 仍然有效。将我的字段从“TextField”更改为“StringField”,效果非常棒。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多