Lucene实战构建索引

搭建lucene的步骤这里就不详细介绍了,无外乎就是下载相关jar包,在eclipse中新建java工程,引入相关的jar包即可

本文主要在没有剖析lucene的源码之前实战一下,通过实战来促进研究

建立索引

下面的程序展示了indexer的使用

package com.wuyudong.mylucene;

import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.Version;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.FileReader;

public class IndexerTest {

  public static void main(String[] args) throws Exception {
    if (args.length != 2) {
      throw new IllegalArgumentException("Usage: java " + IndexerTest.class.getName()
        + " <index dir> <data dir>");
    }
    String indexDir = args[0];         //1 指定目录创建索引
    String dataDir = args[1];          //2 对指定目录中的*.txt文件进行索引

    long start = System.currentTimeMillis();
    IndexerTest indexer = new IndexerTest(indexDir);
    int numIndexed;
    try {
      numIndexed = indexer.index(dataDir, new TextFilesFilter());
    } finally {
      indexer.close();
    }
    long end = System.currentTimeMillis();

    System.out.println("Indexing " + numIndexed + " files took "
      + (end - start) + " milliseconds");
  }

  private IndexWriter writer;

  public IndexerTest(String indexDir) throws IOException {
    Directory dir = FSDirectory.open(new File(indexDir));
    writer = new IndexWriter(dir,            //3 创建IndexWriter
                 new StandardAnalyzer(       //3
                     Version.LUCENE_30),//3
                 true,                       //3
                             IndexWriter.MaxFieldLength.UNLIMITED); //3
  }

  public void close() throws IOException {
    writer.close();                             //4 关闭IndexWriter
  }

  public int index(String dataDir, FileFilter filter)
    throws Exception {

    File[] files = new File(dataDir).listFiles();

    for (File f: files) {
      if (!f.isDirectory() &&
          !f.isHidden() &&
          f.exists() &&
          f.canRead() &&
          (filter == null || filter.accept(f))) {
        indexFile(f);
      }
    }

    return writer.numDocs();                     //5 返回被索引的文档数
  }

  private static class TextFilesFilter implements FileFilter {
    public boolean accept(File path) {
      return path.getName().toLowerCase()        //6 只索引*.txt文件,采用FileFilter
             .endsWith(".txt");                  //6
    }
  }

  protected Document getDocument(File f) throws Exception {
    Document doc = new Document();
    doc.add(new Field("contents", new FileReader(f)));      //7 索引文件内容
    doc.add(new Field("filename", f.getName(),              //8 索引文件名
                Field.Store.YES, Field.Index.NOT_ANALYZED));//8
    doc.add(new Field("fullpath", f.getCanonicalPath(),     //9 索引文件完整路径
                Field.Store.YES, Field.Index.NOT_ANALYZED));//9
    return doc;
  }

  private void indexFile(File f) throws Exception {
    System.out.println("Indexing " + f.getCanonicalPath());
    Document doc = getDocument(f);
    writer.addDocument(doc);                              //10 向Lucene索引中添加文档
  }
}

在eclipse中配置好参数:

E:\luceneinaction\index E:\luceneinaction\lia2e\src\lia\meetlucene\data

运行结果如下:

Indexing E:\luceneinaction\lia2e\src\lia\meetlucene\data\apache1.0.txt
Indexing E:\luceneinaction\lia2e\src\lia\meetlucene\data\apache1.1.txt
Indexing E:\luceneinaction\lia2e\src\lia\meetlucene\data\apache2.0.txt
Indexing E:\luceneinaction\lia2e\src\lia\meetlucene\data\cpl1.0.txt
Indexing E:\luceneinaction\lia2e\src\lia\meetlucene\data\epl1.0.txt
Indexing E:\luceneinaction\lia2e\src\lia\meetlucene\data\freebsd.txt
Indexing E:\luceneinaction\lia2e\src\lia\meetlucene\data\gpl1.0.txt
Indexing E:\luceneinaction\lia2e\src\lia\meetlucene\data\gpl2.0.txt
Indexing E:\luceneinaction\lia2e\src\lia\meetlucene\data\gpl3.0.txt
Indexing E:\luceneinaction\lia2e\src\lia\meetlucene\data\lgpl2.1.txt
Indexing E:\luceneinaction\lia2e\src\lia\meetlucene\data\lgpl3.txt
Indexing E:\luceneinaction\lia2e\src\lia\meetlucene\data\lpgl2.0.txt
Indexing E:\luceneinaction\lia2e\src\lia\meetlucene\data\mit.txt
Indexing E:\luceneinaction\lia2e\src\lia\meetlucene\data\mozilla1.1.txt
Indexing E:\luceneinaction\lia2e\src\lia\meetlucene\data\mozilla_eula_firefox3.txt
Indexing E:\luceneinaction\lia2e\src\lia\meetlucene\data\mozilla_eula_thunderbird2.txt
Indexing 16 files took 888 milliseconds

在index文件内会产生索引文件:

由于被索引的文件都很小,数量也不大(如下图),但是会花费888ms,还是很让人不安

总体说来,搜索索引比建立索引重要,因为搜索很多次,而索引只是建立一次

搜索索引

接下来将创建一个程序 来对上面创建的索引进行搜索:

import org.apache.lucene.document.Document;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.Directory;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.util.Version;

import java.io.File;
import java.io.IOException;

public class SearcherTest {

  public static void main(String[] args) throws IllegalArgumentException,
        IOException, ParseException {
    if (args.length != 2) {
      throw new IllegalArgumentException("Usage: java " + SearcherTest.class.getName()
        + " <index dir> <query>");
    }

    String indexDir = args[0];               //1 解析输入的索引路径
    String q = args[1];                      //2 解析输入的查询字符串   

    search(indexDir, q);
  }

  public static void search(String indexDir, String q)
    throws IOException, ParseException {

    Directory dir = FSDirectory.open(new File(indexDir)); //3 打开索引文件
    IndexSearcher is = new IndexSearcher(dir);   //3   

    QueryParser parser = new QueryParser(Version.LUCENE_30, // 4 解析查询字符串
                                         "contents",  //4
                     new StandardAnalyzer(          //4
                       Version.LUCENE_30));  //4
    Query query = parser.parse(q);              //4
    long start = System.currentTimeMillis();
    TopDocs hits = is.search(query, 10); //5 搜索索引
    long end = System.currentTimeMillis();

    System.err.println("Found " + hits.totalHits +   //6 记录索引状态
      " document(s) (in " + (end - start) +        // 6
      " milliseconds) that matched query ‘" +     // 6
      q + "‘:");                                   // 6

    for(ScoreDoc scoreDoc : hits.scoreDocs) {
      Document doc = is.doc(scoreDoc.doc);               //7 返回匹配文本
      System.out.println(doc.get("fullpath"));  //8 显示匹配文件名
    }

    is.close();                                //9 关闭IndexSearcher
  }
}

设置好参数:E:\luceneinaction\index patent

运行结果如下:

Found 8 document(s) (in 12 milliseconds) that matched query ‘patent‘:
E:\luceneinaction\lia2e\src\lia\meetlucene\data\cpl1.0.txt
E:\luceneinaction\lia2e\src\lia\meetlucene\data\mozilla1.1.txt
E:\luceneinaction\lia2e\src\lia\meetlucene\data\epl1.0.txt
E:\luceneinaction\lia2e\src\lia\meetlucene\data\gpl3.0.txt
E:\luceneinaction\lia2e\src\lia\meetlucene\data\apache2.0.txt
E:\luceneinaction\lia2e\src\lia\meetlucene\data\gpl2.0.txt
E:\luceneinaction\lia2e\src\lia\meetlucene\data\lpgl2.0.txt
E:\luceneinaction\lia2e\src\lia\meetlucene\data\lgpl2.1.txt

可以看到速度很快(12ms),打印的是文件的绝对路径,这是因为indexer存储的是文件的绝对路径

时间: 2024-10-07 00:15:11

Lucene实战构建索引的相关文章

Lucene实战-Indexer索引创建

package com.lin.util; import java.io.File; import java.io.FileFilter; import java.io.FileReader; import java.io.IOException; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.IndexWrit

【Lucene实验1】构建索引

一.实验名称:构建索引 二.实验日期:2013/9/21 三.实验目的: 1)        能理解Lucene中的Document-Field结构的数据建模过程: 2)        能编针对特定数据生成索引文件. 四.实验用的仪器和材料: MyEclipse 10,JDK 五.实验的步骤和方法: 题目一:在指定目录生成表示3本书的索引,要求建立3个document分别存放书名数据.把生成的索引文件截好图(复合索引与一般索引各生成一次) 图1:一般索引的截图 图2:复合索引的截图 题目二:修改

【Lucene】Apache Lucene全文检索引擎架构之构建索引

上一篇博文中已经对全文检索有了一定的了解,这篇文章主要来总结一下全文检索的第一步:构建索引.其实上一篇博文中的示例程序已经对构建索引写了一段程序了,而且那个程序还是挺完善的.不过从知识点的完整性来考虑,我想从Lucene的添加文档.删除文档.修改文档以及文档域加权四个部分来展开对构建索引的总结,也便于我后期的查看.会重点分析一下删除文档(因为有两中方式)和文档域加权这(实际中会用到比较多)两个部分. 1. 准备阶段 新建一个maven工程,pom.xml如下: <project xmlns=&quo

Lucene底层原理和优化经验分享(1)-Lucene简介和索引原理

基于Lucene检索引擎我们开发了自己的全文检索系统,承担起后台PB级.万亿条数据记录的检索工作,这里向大家分享下Lucene底层原理研究和一些优化经验. 从两个方面介绍: 1. Lucene简介和索引原理 2. Lucene优化经验总结 1. Lucene简介和索引原理 该部分从三方面展开:Lucene简介.索引原理.Lucene索引实现. 1.1 Lucene简介 Lucene最初由鼎鼎大名Doug Cutting开发,2000年开源,现在也是开源全文检索方案的不二选择,它的特点概述起来就是

Lucene实战(第2版)》

<Lucene实战(第2版)>基于Apache的Lucene 3.0,从Lucene核心.Lucene应用.案例分析3个方面详细系统地介绍了Lucene,包括认识Lucene.建立索引.为应用程序添加搜索功能.高级搜索技术.扩展搜索.使用Tika提取文本.Lucene的高级扩展.使用其他编程语言访问Lucene.Lucene管理和性能调优等内容,最后还提供了三大经典成功案例,为读者展示了一个奇妙的搜索世界. 首先你先确定Lucene的版本,然后查一下对应官方的api文档,看看你用的那个方法是实

【Lucene】Lucene 学习之索引文件结构

Lucene 索引文件结构 基本概念 索引(index) Lucene的索引由许多个文件组成,这些文件放在同一个目录下 段(segment) 一个Lucene的索引由多个段组成,段与段之间是独立的.添加新的文档时可以生成新的段,达到阈值(段的个数,段中包含的文件数等)时,不同的段可以合并. 在文件夹下,具有相同前缀的文件属于同一个段 segments.gen 和 segments_N(N表示一个具体数字,eg:segments_5)是段的元数据文件,他们保存了段的属性信息. 文档(documen

MongoDB数据量较大时如何构建索引--减少业务最少影响

在数据量较大或请求量较大,直接建立索引对性能有显著影响时,可以利用复制集(数据量较大时一般为线上环境,使用复制集为必然选择或者使用分片.)中部分机器宕机不影响复制集工作的特性,继而建立索引. 备注:添加索引的表使用WT引擎,数据量有1.5亿左右. 1. 副本集配置参数 节点1: $ more shard1.conf dbpath=/data/users/mgousr01/mongodb/dbdata/shard1_1 logpath=/data/users/mgousr01/mongodb/lo

Lucene 4.9索引txt文件

暂时只是跑起来了,不知道是否正确,困了,睡觉了,改天再弄.搜索那块是分页的,也没仔细弄... 参考着 http://blog.csdn.net/kingskyleader/article/details/8444739 在data下放了三个txt... S:\lucene\data\永生.txt S:\lucene\data\1.txt S:\lucene\data\2.txt 永生是本小说,汉语的应该没有英文. 1.txt 内容: hello 2.txt 内容: hi hello  哈哈 程序

lucene学习-创建索引

本文的lucene是基于lucene3.5版本. 使用lucene实现搜索引擎开发,核心的部分是建立索引和搜索.本节主要是记录创建索引部分的内容. 创建的索引结构如图所示. 创建索引的步骤分为以下几个步骤: 1.建立索引器IndexWriter 2.创建文档对象Document 3.建立信息对象字段Field 4.将Field对象添加到Document 5.将Document对象添加到IndexWriter对象中 下面简要介绍几个核心对象. (1).创建IndexWriter对象. IndexW