Lucene - 添加文档操作

  • 简述

    索引过程是Lucene提供的核心功能之一。下图说明了索引过程和类的使用。IndexWriter 是索引过程中最重要、最核心的组件。
    索引过程
    我们将包含Field(s) 的Document(s)添加到 IndexWriter,它使用Analyzer分析 Document(s) ,然后根据需要创建/打开/编辑索引并将它们存储/更新在Directory 中IndexWriter用于更新或创建索引。它不用于读取索引。
    现在,我们将通过一个基本示例向您展示一个逐步的过程,以帮助您了解索引过程。
  • 创建文档

    • 创建一个从文本文件中获取 lucene 文档的方法。
    • 创建各种类型的字段,这些字段是键值对,包含键作为名称和值作为要索引的内容。
    • 设置要分析或不分析的字段。在我们的例子中,只分析内容,因为它可以包含搜索操作中不需要的数据,例如 a、am、are、an 等。
    • 将新创建的字段添加到文档对象并将其返回给调用者方法。
    
    private Document getDocument(File file) throws IOException {
       Document document = new Document();
       
       //index file contents
       Field contentField = new Field(LuceneConstants.CONTENTS, 
          new FileReader(file));
       
       //index file name
       Field fileNameField = new Field(LuceneConstants.FILE_NAME,
          file.getName(),
          Field.Store.YES,Field.Index.NOT_ANALYZED);
       
       //index file path
       Field filePathField = new Field(LuceneConstants.FILE_PATH,
          file.getCanonicalPath(),
          Field.Store.YES,Field.Index.NOT_ANALYZED);
       document.add(contentField);
       document.add(fileNameField);
       document.add(filePathField);
       return document;
    }   
    
  • 创建一个索引写入器

    IndexWriter 类充当在索引过程中创建/更新索引的核心组件。按照以下步骤创建一个 IndexWriter -
    Step 1 − 创建IndexWriter 对象。
    Step 2 − 创建一个 Lucene 目录,该目录应指向要存储索引的位置。
    Step 3 - 初始化使用索引目录创建的 IndexWriter 对象,一个具有版本信息和其他必需/可选参数的标准分析器。
    
    private IndexWriter writer;
    public Indexer(String indexDirectoryPath) throws IOException {
       //this directory will contain the indexes
       Directory indexDirectory = 
          FSDirectory.open(new File(indexDirectoryPath));
       
       //create the indexer
       writer = new IndexWriter(indexDirectory, 
          new StandardAnalyzer(Version.LUCENE_36),true,
          IndexWriter.MaxFieldLength.UNLIMITED);
    }
    
  • 开始索引过程

    以下程序显示了如何启动索引过程 -
    
    private void indexFile(File file) throws IOException {
       System.out.println("Indexing "+file.getCanonicalPath());
       Document document = getDocument(file);
       writer.addDocument(document);
    }
    
  • 示例应用

    为了测试索引过程,我们需要创建一个 Lucene 应用程序测试。
    描述
    1
    创建一个名称的项目LuceneFirstApplication一个包下com.jc2182.lucene作为解释Lucene的-第一个应用程序一章。您也可以使用在Lucene - First Application章节中创建的项目来理解本章的索引过程。
    2
    创建LuceneConstants.java,TextFileFilter.javaIndexer.java作为解释Lucene的-第一个应用程序的章节。保持其余文件不变。
    3
    如下所述创建LuceneTester.java
    4
    清理并构建应用程序以确保业务逻辑按照要求工作。

    LuceneConstants.java

    此类用于提供要在整个示例应用程序中使用的各种常量。
    
    package com.jc2182.lucene;
    public class LuceneConstants {
       public static final String CONTENTS = "contents";
       public static final String FILE_NAME = "filename";
       public static final String FILE_PATH = "filepath";
       public static final int MAX_SEARCH = 10;
    }
    

    TextFileFilter.java

    这个类用作 .txt 文件过滤器。
    
    package com.jc2182.lucene;
    import java.io.File;
    import java.io.FileFilter;
    public class TextFileFilter implements FileFilter {
       @Override
       public boolean accept(File pathname) {
          return pathname.getName().toLowerCase().endsWith(".txt");
       }
    }
    

    Indexer.java

    此类用于索引原始数据,以便我们可以使用 Lucene 库对其进行搜索。
    
    package com.jc2182.lucene;
    import java.io.File;
    import java.io.FileFilter;
    import java.io.FileReader;
    import java.io.IOException;
    import org.apache.lucene.analysis.standard.StandardAnalyzer;
    import org.apache.lucene.document.Document;
    import org.apache.lucene.document.Field;
    import org.apache.lucene.index.CorruptIndexException;
    import org.apache.lucene.index.IndexWriter;
    import org.apache.lucene.store.Directory;
    import org.apache.lucene.store.FSDirectory;
    import org.apache.lucene.util.Version;
    public class Indexer {
       private IndexWriter writer;
       public Indexer(String indexDirectoryPath) throws IOException {
          //this directory will contain the indexes
          Directory indexDirectory = 
             FSDirectory.open(new File(indexDirectoryPath));
          //create the indexer
          writer = new IndexWriter(indexDirectory, 
             new StandardAnalyzer(Version.LUCENE_36),true,
             IndexWriter.MaxFieldLength.UNLIMITED);
       }
       public void close() throws CorruptIndexException, IOException {
          writer.close();
       }
       private Document getDocument(File file) throws IOException {
          Document document = new Document();
          //index file contents
          Field contentField = new Field(LuceneConstants.CONTENTS, 
             new FileReader(file));
          
          //index file name
          Field fileNameField = new Field(LuceneConstants.FILE_NAME,
             file.getName(),
             Field.Store.YES,Field.Index.NOT_ANALYZED);
          
          //index file path
          Field filePathField = new Field(LuceneConstants.FILE_PATH,
             file.getCanonicalPath(),
             Field.Store.YES,Field.Index.NOT_ANALYZED);
          document.add(contentField);
          document.add(fileNameField);
          document.add(filePathField);
          return document;
       }   
       private void indexFile(File file) throws IOException {
          System.out.println("Indexing "+file.getCanonicalPath());
          Document document = getDocument(file);
          writer.addDocument(document);
       }
       public int createIndex(String dataDirPath, FileFilter filter) 
          throws IOException {
          //get all files in the data directory
          File[] files = new File(dataDirPath).listFiles();
          for (File file : files) {
             if(!file.isDirectory()
                && !file.isHidden()
                && file.exists()
                && file.canRead()
                && filter.accept(file)
             ){
                indexFile(file);
             }
          }
          return writer.numDocs();
       }
    }
    

    LuceneTester.java

    该类用于测试 Lucene 库的索引能力。
    
    package com.jc2182.lucene;
    import java.io.IOException;
    public class LuceneTester {
       
       String indexDir = "E:\\Lucene\\Index";
       String dataDir = "E:\\Lucene\\Data";
       Indexer indexer;
       
       public static void main(String[] args) {
          LuceneTester tester;
          try {
             tester = new LuceneTester();
             tester.createIndex();
          } catch (IOException e) {
             e.printStackTrace();
          } 
       }
       private void createIndex() throws IOException {
          indexer = new Indexer(indexDir);
          int numIndexed;
          long startTime = System.currentTimeMillis(); 
          numIndexed = indexer.createIndex(dataDir, new TextFileFilter());
          long endTime = System.currentTimeMillis();
          indexer.close();
          System.out.println(numIndexed+" File indexed, time taken: "
             +(endTime-startTime)+" ms");     
       }
    }
    
  • 数据和索引目录创建

    我们使用了从 record1.txt 到 record10.txt 的 10 个文本文件,其中包含学生的姓名和其他详细信息,并将它们放在目录中 E:\Lucene\Data. 运行 E:\Lucene\Index. 程序后,您可以看到在该文件夹中创建的索引文件列表
  • 运行程序

    完成源、原始数据、数据目录和索引目录的创建后,您可以继续编译和运行程序。 为此,请保持 LuceneTester.Java 文件选项卡处于活动状态并使用 Eclipse IDE 中提供的 Run 选项或使用 Ctrl + F11 编译并运行您的 LuceneTester 应用程序。 如果您的应用程序成功运行,它将在 Eclipse IDE 的控制台中打印以下消息 -
    
    Indexing E:\Lucene\Data\record1.txt
    Indexing E:\Lucene\Data\record10.txt
    Indexing E:\Lucene\Data\record2.txt
    Indexing E:\Lucene\Data\record3.txt
    Indexing E:\Lucene\Data\record4.txt
    Indexing E:\Lucene\Data\record5.txt
    Indexing E:\Lucene\Data\record6.txt
    Indexing E:\Lucene\Data\record7.txt
    Indexing E:\Lucene\Data\record8.txt
    Indexing E:\Lucene\Data\record9.txt
    10 File indexed, time taken: 109 ms
    
    成功运行程序后,您将拥有以下内容 索引目录−
    Lucene Index Directory