`
devsky
  • 浏览: 25400 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

关于全文检索的文章(使用技术Lucene3.0)

阅读更多

Lucene3.0全文搜索简单应用

由于项目的要求,用到了全文搜索技术,上网查了许多资料,结合本项目实际情况,现将lucene3.0总结如下:

1.首先了解一下lucene中的一些基本概念:

 假设我们的电脑的目录中含有很多文本文档,我们需要查找哪些文档含有某个关键词。为了实现这种功能,我们首先利用 Lucene 对这个目录中的文档建立索引,然后在建立好的索引中搜索我们所要查找的文档。

 

(1)建立索引
为了对文档进行索引,Lucene 提供了五个基础的类,他们分别是 Document, Field, IndexWriter, Analyzer, Directory。下面我们分别介绍一下这五个类的用途:

Document

Document 是用来描述文档的,这里的文档可以指一个 HTML 页面,一封电子邮件,或者是一个文本文件。一个 Document 对象由多个 Field 对象组成的。可以把一个 Document 对象想象成数据库中的一个记录,而每个 Field 对象就是记录的一个字段。

Field
Field 对象是用来描述一个文档的某个属性的,比如一封电子邮件的标题和内容可以用两个 Field 对象分别描述。

Analyzer

在一个文档被索引之前,首先需要对文档内容进行分词处理,这部分工作就是由 Analyzer 来做的。Analyzer 类是一个抽象类,它有多个实现。针对不同的语言和应用需要选择适合的 Analyzer。Analyzer 把分词后的内容交给 IndexWriter 来建立索引。

IndexWriter

IndexWriter 是 Lucene 用来创建索引的一个核心的类,他的作用是把一个个的 Document 对象加到索引中来。

Directory

这个类代表了 Lucene 的索引的存储的位置,这是一个抽象类,它目前有两个实现,第一个是 FSDirectory,它表示一个存储在文件系统中的索引的位置。第二个是 RAMDirectory,它表示一个存储在内存当中的索引的位置。

熟悉了建立索引所需要的这些类后,我们开始对某个目录下面的htm文件l建立索引了,在建立的过程中,需将这些html文件转化为文本文件,下面给出建立索引类的源代码。


import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

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.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.SimpleFSDirectory;
import org.htmlparser.Parser;
import org.htmlparser.util.ParserException;
import org.htmlparser.visitors.HtmlPage;
import org.wltea.analyzer.lucene.IKAnalyzer;

 

public class LuceneIndex
{
 public static final String CONTENT_KEY_NAME = "content";//内容的键
 public static final String FILE_KEY_NAME = "filenamddde";//文件名的键
 public IndexWriter mWriter = null;//用于写入索引的对象

 /**
  * @功能描述 打开Lucene实例
  * @输入参数 indexDirectory为索引存放目录,create为创建索引
  * @反馈值 无
  */
 public void openLuceneIndex(Directory indexDirectory, boolean create) throws CorruptIndexException, LockObtainFailedException, IOException
 {
  close();
  mWriter = new IndexWriter(indexDirectory, new IKAnalyzer(), create, MaxFieldLength.LIMITED);
  mWriter.setUseCompoundFile(true);
 }

 /**
  * @功能描述 将HTML转化为Text
  * @输入参数
  * @反馈值
  */
 public static String extractHtml(String inputHtml) throws ParserException
 {
  Parser htmlParser = Parser.createParser(inputHtml,"utf-8");
  HtmlPage thePage = new HtmlPage(htmlParser);
  htmlParser.visitAllNodesWith(thePage);
  String body = thePage.getBody().asString();
  body = body.replaceAll("[ \\t\\n\\r\\f( |gt) ]+", " ");
  System.out.println(body);
  String title = thePage.getTitle();
  return title + " " + body;
 }

 /**
  * @throws Exception
  * @功能描述 向已经打开的Lucene实例里面添加新的索引
  * @输入参数
  * @反馈值
  */
 public void indexTxt(File f) throws Exception
 {
  if (mWriter == null)
  {
   throw new Exception("Lucene Index not Opened!");
  }
  BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(f), "GBK"));
  StringBuffer sb = new StringBuffer();
  String temp = null;
  while ((temp = reader.readLine()) != null)
  {
   sb.append(temp);
  }
  reader.close();
  indexString(f.getName(), sb.toString());
 }

 /**
  * @功能描述 索引HTML文件
  * @输入参数
  * @反馈值
  */
 public void indexHtml(File f) throws Exception
 {
  BufferedReader br = null;
  try
  {
   StringBuffer sb = new StringBuffer();
   br = new BufferedReader(new InputStreamReader(new FileInputStream(f),"utf-8"));

   String temp = null;
   while ((temp = br.readLine()) != null)
   {
    sb.append(temp + "\r\n");
   }

   String theHtml = sb.toString();
   String thePlainText = extractHtml(theHtml);

   indexString(f.getName(), thePlainText);
  } catch (Exception ex)
  {
   throw ex;
  } finally
  {
   if (br != null)
   {
    br.close();
   }
  }
 }

 /**
  * @功能描述  索引字符串
  * @输入参数 
  * @反馈值   
  */
 public void indexString(String key, String content) throws Exception
 {
  if (mWriter == null)
  {
   throw new Exception("Lucene Index not Opened!");
  }
 
  Document doc = new Document();
 
  doc.add(new Field(CONTENT_KEY_NAME, content, Field.Store.YES, Field.Index.ANALYZED));
  doc.add(new Field(FILE_KEY_NAME, key, Field.Store.YES, Field.Index.ANALYZED));
 
  mWriter.addDocument(doc);
  mWriter.optimize();
 }

 public void close()
 {
  try
  {
   if (mWriter != null)
   {
    mWriter.close();
    mWriter = null;
   }
  } catch (Exception e)
  {
  }
 }

 /**
  * @功能描述 建立索引
  * @输入参数 indexDirectory为索引存放路径,docDirectory为文档存放路径
  * @反馈值
  */
 public static void indexService(String indexDirectory, String docDirectory) throws Exception
 {
  LuceneIndex index = new LuceneIndex();
  Directory directory = null;
  try
  {
   directory = new SimpleFSDirectory(new File(indexDirectory));// new
   index.openLuceneIndex(directory, true);
   indexDirectory(index, new File(docDirectory));
   System.out.println("索引完成");
  } catch (Exception e)
  {
   throw e;
  } finally
  {
   index.close();
  }
 }

 /**
  * @功能描述 遍历索引一个目录下面的所有HTML文件
  * @输入参数
  * @反馈值
  */
 public static void indexDirectory(LuceneIndex index, File directory) throws Exception
 {
  File[] fileList = directory.listFiles();
  for (File f : fileList)
  {
   if (f.isFile())
   {
    if (f.getName().endsWith(".html") || f.getName().endsWith(".htm"))
    {
     System.out.println("现在开始索引:" + f.getName());
     index.indexHtml(f);
    }
   } else if (f.isDirectory())
   {
    indexDirectory(index, f);
   }
  }
 }
 
}

 

(2)搜索文档
利用 Lucene 进行搜索就像建立索引一样也是非常方便的。在上面一部分中,我们已经为一个目录下的文本文档建立好了索引,现在我们就要在这个索引上进行搜索以找到包含某个关键词或短语的文档。Lucene 提供了几个基础的类来完成这个过程,它们分别是呢 IndexSearcher, Term, Query, TermQuery, Hits. 下面我们分别介绍这几个类的功能。

Query
这是一个抽象类,他有多个实现,比如 TermQuery, BooleanQuery, PrefixQuery. 这个类的目的是把用户输入的查询字符串封装成 Lucene 能够识别的 Query。

Term
Term 是搜索的基本单位,一个 Term 对象有两个 String 类型的域组成。生成一个 Term 对象可以有如下一条语句来完成:Term term = new Term(“fieldName”,”queryWord”); 其中第一个参数代表了要在文档的哪一个 Field 上进行查找,第二个参数代表了要查询的关键词。

TermQuery
TermQuery 是抽象类 Query 的一个子类,它同时也是 Lucene 支持的最为基本的一个查询类。生成一个 TermQuery 对象由如下语句完成: TermQuery termQuery = new TermQuery(new Term(“fieldName”,”queryWord”)); 它的构造函数只接受一个参数,那就是一个 Term 对象。

IndexSearcher

IndexSearcher 是用来在建立好的索引上进行搜索的。它只能以只读的方式打开一个索引,所以可以有多个 IndexSearcher 的实例在一个索引上进行操作。

Hits
Hits 是用来保存搜索的结果的。

介绍完这些搜索所必须的类之后,我们就开始在之前所建立的索引上进行搜索了,下面给出搜索类的源代码:

 

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.wltea.analyzer.lucene.IKQueryParser;

 

public class LuceneSearch
{
 public IndexSearcher mSearch = null;//用于搜索的对象

 /**
  * @功能描述 打开一个索引目录
  * @输入参数  indexDirectory 索引目录
  * @反馈值
  */
 public void openLuceneSearch(Directory indexDirectory) throws CorruptIndexException, IOException
 {
  mSearch = new IndexSearcher(indexDirectory, true);
 }

 public void close()
 {
  try
  {
   if (mSearch != null)
   {
    mSearch.close();
   }
  } catch (Exception e)
  {
  }
 }

 /**
  * @功能描述 搜索关键字
  * @输入参数 keyword为搜索关键字,start为起始点,top为返回多少条数据
  * @反馈值
  */
 public List<Document> search(String keyword, int start, int top) throws Exception
 {
  if (mSearch == null)
  {
   throw new Exception("没有初始化 Lucene Index Search");
  }

  Query query = IKQueryParser.parse(LuceneIndex.CONTENT_KEY_NAME, keyword);
  return search(query, start, top);
 }
 
 /**
  * @功能描述 根据已经定制好的查询返回查询结果
  * @输入参数 query 已经定制好的查询,start 起始结果,count 结果数量
  * @反馈值
  */
 public List<Document> search(Query query, int start, int count) throws Exception
 {
  if (mSearch == null)
  {
   throw new Exception("没有初始化 Lucene Index Search");
  }

  List<Document> docs = new ArrayList<Document>();
  TopDocs theDocs = mSearch.search(query, 1000);

  int resultCount = theDocs.scoreDocs.length;
  start = Math.min(start, resultCount);
  int end = Math.min(start + count, resultCount);

  for (int i = start; i < end; ++i)
  {
   Document doc = mSearch.doc(theDocs.scoreDocs[i].doc);
   docs.add(doc);
  }

  return docs;
 }
 
}


(3)主方法进行测试

 

 import java.io.File;
import java.util.List;

import org.apache.lucene.document.Document;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.SimpleFSDirectory;

 

public class TestMain
{
 public static void main(String[] args) throws Exception
 {
  if (args.length == 3)
  {
   if (args[0].equalsIgnoreCase("createindex"))
   {
    String indexDirectory = args[1];//最终放置索引位置D:\2
    String docDirectory = args[2];//文档路径D:\1
    LuceneIndex.indexService(indexDirectory, docDirectory);
   }
  } else if (args.length == 4)
  {
   if (args[0].equalsIgnoreCase("search"))
   {
    LuceneSearch search = new LuceneSearch();
    try
    {
     String indexDirectory = args[1];//D:\2
     String keyword = args[2];//要查找的字
     int top = Integer.parseInt(args[3]);//查找范围

     System.out.println("关键字为 :" + keyword);

     Directory directory = new SimpleFSDirectory(new File(indexDirectory));

     search.openLuceneSearch(directory);
     List<Document> docs = search.search(keyword, 0, top);
     System.out.println("结果总数" + docs.size());

     for (Document doc : docs)
     {
      System.out.println("结果:" + doc.getField(LuceneIndex.FILE_KEY_NAME).stringValue());
     }
    } catch (Exception e)
    {
     e.printStackTrace();
     return;
    } finally
    {
     search.close();
    }
   }
  }
 }

}

点击myeclipse中,绿色有个向右的箭头旁边的向下的按钮,选择open run dialog对话框,在java Application上点击右键,选择new,新建一个起名为index,然后选择index,在Arguments中的Program arguments中输入,

createindex  D:\2  D:\1  点应用,就开始创建索引。

 

同理创建一个search应用,在Arguments 中的Program arguments中输入

search D:\2  要搜索的关键字  搜索范围(默认值,随便给1000)

点应用,开始搜索,查看控制台有没有输出,如果有,说明成功,如果没有,在看看是不是编码的问题。

 

 

 

 

分享到:
评论

相关推荐

    全文检索 lucene 3.0

    全文检索 lucene 3.0 叶涛 全文检索 lucene 3.0 叶涛 非常好用.上手极快!

    Lucene3.0全文信息检索

    采用Lucene3.0 API实现对目标系统的全文信息检索功能,效率高效(Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包)

    lucene3.0全文检索入门实例

    Lucene3.0和Lucene2.0API有多处改动,该实例用Luence3.0实现

    lucene3.0-lib

    Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎...

    Lucene 3.0 原理与代码分析

    本系列文章将详细描述几乎最新版本的Lucene的基本原理和...Lucene学习总结之一:全文检索的基本原理 http://www.cnblogs.com/forfuture1978/archive/2009/12/14/1623594.html Lucene学习总结之二:Lucene的总体架构 ...

    Lucene 3.0 原理与代码分析PDF

    Lucene学习总结之一:全文检索的基本原理 Lucene学习总结之二:Lucene的总体架构 Lucene学习总结之三:Lucene的索引文件格式(1) Lucene学习总结之三:Lucene的索引文件格式(2) Lucene学习总结之三:Lucene的...

    汤阳光_Lucene3.0课程

    我们使用Lucene,主要是做站内搜索,即对一个系统内的资源进行搜索。如BBS、BLOG中的文章搜索,网上商店中的商品搜索等。使用Lucene的项目[In ...所以,学完Lucene后我们就可以为自已的系统增加全文检索的功能。

    lucene3.0原理与分析

    开放源码的lucene是当前使用最普及的全文检索工具包,对lucene的源码的研究对于程序员的对搜索引擎的理解会更有帮助。

    Lucene 3.0 原理与代码分析完整版

    1.1 Lucene学习总结之一:全文检索的基本原理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.2 Lucene学习总结之二:Lucene的总体架构 . . . . . . . . . . . . ...

    Lucene3.0课程

    全文检索技术,可以对全文进行精确的检索,将检索到的内容添加高亮的效果,非常好用。

    全文搜索引擎lucene入门

    全文检索lucene入门,结合全文检索原理分析lucene.帮助你更快掌握lucene

    盘古分词+Lucene

    做中文全文检索、搜索必备。 里面有实例代码。 相互学习!

    解密搜索引擎技术实战Java精华版

    在全文检索部分,结合Lucene3.0介绍了搜索引擎的原理与进展。用简单的例子介绍了Lucene的最新应用方法。包括完整的搜索实现过程:从完成索引到搜索用户界面的实现。本书还进一步介绍了实现准实时搜索的方法,展示了...

    Apache-Lucene.Net-3.0.3-RC2

    Lucene.net是Lucene的.net移植版本,是一个开源的全文检索引擎开发包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎。开发人员可以基于Lucene.net实现全文检索的...

    Luncene3.0从入门到精通

    Lucene3.0从入门到精通,适合所有想做全文检索,垂直搜索方面的开发人员。从简单到深入,各种例子,各种注释很齐全。

    IKAnalyzer 3.0 中文分词器

    1.IKAnalyzer3.0介绍 IKAnalyzer是一个开源的,基于java... * 针对Lucene全文检索优化的查询分析器IKQueryParser(作者吐血推荐);采用歧义分析算法优化查询关键字的搜索排列组合,能极大的提高Lucene检索的命中率。

    Hibernate Search 3.0 GA

    它是hibernate对著名的全文检索系统Lucene的一个集成方案,作用在于对数据表中某些内容庞大的字段(如声明为text的字段)建立全文索引,这样通过hibernate search就可以对这些字段进行全文检索后获得相应的POJO,...

    EasyJForum v3.0 Java技术的社区论坛.rar

     EasyJForum 的基本设计宗旨是简洁,因此仅仅采用了最基本的 JSP,JDBC 等技术以获取最高的性能和可扩展性,同时采用了缓存和连接池等技术以加强性能,采用了 lucene 包以实现全文检索。此外没有采用任何其它复杂的...

Global site tag (gtag.js) - Google Analytics