Lucene简介&Lucene示例

lucene是一个很容易上手,纯java语言的全文索引检索工具包。
    Lucene的作者是资深的全文索引/检索专家,最开始发布在他本人的主页上,2001年10月贡献给APACHE,成为APACHE基金jakarta的一个子项目。
    目前,lucene广泛用于全文索引/检索的项目中。


    Lucene 原理
lucene的检索算法属于索引检索,即用空间来换取时间,对需要检索的文件、字符流进行全文索引,在检索的时候对索引进行快速的检索,得到检索位置,这个位置记录检索词出现的文件路径或者某个关键词。
    在使用数据库的项目中,不使用数据库进行检索的原因主要是:数据库在非精确查询的时候使用查询语言“like %keyword%”,对数据库进行查询是对所有记录遍历,并对字段进行“%keyword%”匹配,在数据库的数据庞大以及某个字段存储的数据量庞大的时候,这种遍历是致命的,它需要对所有的记录进行匹配查询。因此,lucene主要适用于文档集的全文检索,以及海量数据库的模糊检索,特别是对数据库的 xml或者大数据的字符类型。
 
    全文检索的实现机制
Lucene的API接口设计的比较通用,输入输出结构都很像数据库的表==>记录==>字段,所以很多传统的应用的文件、数据库等都可以比较方便的映射到Lucene的存储结构/接口中。总体上看:可以先把Lucene当成一个支持全文索引的数据库系统。
比较一下Lucene和数据库:
 
Lucene 数据库
索引数据源:doc(field1,field2...) doc(field1,field2...)
\ indexer /
_____________
| Lucene Index|
--------------
/ searcher \
结果输出:Hits(doc(field1,field2) doc(field1...))
索引数据源:record(field1,field2...) record(field1..)
\ SQL: insert/
_____________
| DB Index |
-------------
/ SQL: select \
结果输出:results(record(field1,field2..) record(field1...))
Document:一个需要进行索引的“单元”
一个Document由多个字段组成
Record:记录,包含多个字段
Field:字段 Field:字段
Hits:查询结果集,由匹配的Document组成 RecordSet:查询结果集,由多个Record组成

 

 
全文检索 ≠ like "%keyword%"
-------------------------------------------------------------------------
Lucene作为一个全文检索引擎,其具有如下突出的优点:
(1)索引文件格式独立于应用平台。Lucene定义了一套以8位字节为基础的索引文件格式,使得兼容系统或者不同平台的应用能够共享建立的索引文件。
  (2)在传统全文检索引擎的倒排索引的基础上,实现了分块索引,能够针对新的文件建立小文件索引,提升索引速度。然后通过与原有索引的合并,达到优化的目的。
  (3)优秀的面向对象的系统架构,使得对于Lucene扩展的学习难度降低,方便扩充新功能。
  (4)设计了独立于语言和文件格式的文本分析接口,索引器通过接受Token流完成索引文件的创立,用户扩展新的语言和文件格式,只需要实现文本分析的接口。
  (5)已经默认实现了一套强大的查询引擎,用户无需自己编写代码即使系统可获得强大的查询能力,Lucene的查询实现中默认实现了布尔操作、模糊查询(Fuzzy Search[11])、分组查询等等。
----------------------------------------------------------------------------------
 
lucence例子:

Windows:
    C:\file\1.txt; 内容:中华人民共和国,全国人民 ,2006年  
    C:\file\2.txt;
    C:\file\3.txt;
    C:\index
step1.建立索引;step2.搜索文档

建立索引
为了对文档进行索引,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,它表示一个存储在内存当中的索引的位置。
熟悉了建立索引所需要的这些类后,我们就开始对某个目录下面的文本文件建立索引了,清单1给出了对某个目录下的文本文件建立索引的源代码:
package com.wpf.lucence; 
 
import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.util.Date; 
 
import org.apache.lucene.analysis.Analyzer; 
import org.apache.lucene.analysis.standard.StandardAnalyzer; 
import org.apache.lucene.document.Document; 
import org.apache.lucene.document.Field; 
import org.apache.lucene.index.IndexWriter; 
 
public class TextFileIndexer { 
    public static void main(String[] args) throws Exception { 
         
        File fileDir = new File("C:\\file"); 
 
         
        File indexDir = new File("c:\\index"); 
        Analyzer luceneAnalyzer = new StandardAnalyzer(); 
        IndexWriter indexWriter = new IndexWriter(indexDir, luceneAnalyzer, 
                true); 
        File[] textFiles = fileDir.listFiles(); 
        long startTime = new Date().getTime(); 
         
        //增加document到索引去 
        for (int i = 0; i < textFiles.length; i++) { 
            if (textFiles[i].isFile() 
                    && textFiles[i].getName().endsWith(".txt")) { 
                System.out.println("File " + textFiles[i].getCanonicalPath() 
                        + "正在被索引...."); 
                String temp = FileReaderAll(textFiles[i].getCanonicalPath(), 
                        "GBK"); 
                System.out.println(temp); 
                Document document = new Document(); 
                Field FieldPath = new Field("path", textFiles[i].getPath(), 
                        Field.Store.YES, Field.Index.NO); 
                Field FieldBody = new Field("body", temp, Field.Store.YES, 
                        Field.Index.TOKENIZED, 
                        Field.TermVector.WITH_POSITIONS_OFFSETS); 
                document.add(FieldPath); 
                document.add(FieldBody); 
                indexWriter.addDocument(document); 
            } 
        } 
        //optimize()方法是对索引进行优化 
        indexWriter.optimize(); 
        indexWriter.close(); 
         
        //测试一下索引的时间 
        long endTime = new Date().getTime(); 
        System.out 
                .println("这花费了" 
                        + (endTime - startTime) 
                        + " 毫秒来把文档增加到索引里面去!" 
                        + fileDir.getPath()); 
    } 
 
    public static String FileReaderAll(String FileName, String charset) 
            throws IOException { 
        BufferedReader reader = new BufferedReader(new InputStreamReader( 
                new FileInputStream(FileName), charset)); 
        String line = new String(); 
        String temp = new String(); 
         
        while ((line = reader.readLine()) != null) { 
            temp += line; 
        } 
        reader.close(); 
        return temp; 
    } 




搜索文档
利用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是用来保存搜索的结果的。
介绍完这些搜索所必须的类之后,我们就开始在之前所建立的索引上进行搜索了,清单2给出了完成搜索功能所需要的代码:
package com.wpf.lucence; 
 
import java.io.IOException; 
 
import org.apache.lucene.analysis.Analyzer; 
import org.apache.lucene.analysis.standard.StandardAnalyzer; 
import org.apache.lucene.queryParser.ParseException; 
import org.apache.lucene.queryParser.QueryParser; 
import org.apache.lucene.search.Hits; 
import org.apache.lucene.search.IndexSearcher; 
import org.apache.lucene.search.Query; 
 
public class TestQuery { 
    public static void main(String[] args) throws IOException, ParseException { 
        Hits hits = null; 
        String queryString = "中华"; 
        Query query = null; 
        IndexSearcher searcher = new IndexSearcher("c:\\index"); 
 
        Analyzer analyzer = new StandardAnalyzer(); 
        try { 
            QueryParser qp = new QueryParser("body", analyzer); 
            query = qp.parse(queryString); 
        } catch (ParseException e) { 
        } 
        if (searcher != null) { 
            hits = searcher.search(query); 
            if (hits.length() > 0) { 
                System.out.println("找到:" + hits.length() + " 个结果!"); 
            } 
        } 
    } 
} 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Lucene是一个开源的全文搜索引擎库,用于实现文本索引和搜索功能。下面是一个Lucene的使用示例: 1. 创建索引: ```java import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; // 创建索引 public class Indexer { public static void main(String[] args) { // 索引存储路径 String indexPath = "path_to_index_directory"; try { // 创建分词器 Analyzer analyzer = new StandardAnalyzer(); // 创建索引配置 IndexWriterConfig config = new IndexWriterConfig(analyzer); // 创建索引目录 Directory directory = FSDirectory.open(Paths.get(indexPath)); // 创建索引写入器 IndexWriter indexWriter = new IndexWriter(directory, config); // 创建文档 Document document = new Document(); document.add(new Field("content", "Hello world!", TextField.TYPE_STORED)); // 将文档添加到索引中 indexWriter.addDocument(document); // 提交索引 indexWriter.commit(); // 关闭索引写入器 indexWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` 2. 搜索索引: ```java import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexReader; import org.apache.lucene.queryparser.classic.QueryParser; 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.Directory; import org.apache.lucene.store.FSDirectory; // 搜索索引 public class Searcher { public static void main(String[] args) { // 索引目录路径 String indexPath = "path_to_index_directory"; try { // 创建分词器 Analyzer analyzer = new StandardAnalyzer(); // 创建索引目录 Directory directory = FSDirectory.open(Paths.get(indexPath)); // 创建索引读取器 IndexReader indexReader = DirectoryReader.open(directory); // 创建索引搜索器 IndexSearcher indexSearcher = new IndexSearcher(indexReader); // 创建查询解析器 QueryParser parser = new QueryParser("content", analyzer); // 创建查询 Query query = parser.parse("Hello"); // 执行查询,获取前n个结果 TopDocs topDocs = indexSearcher.search(query, 10); ScoreDoc[] scoreDocs = topDocs.scoreDocs; // 遍历结果 for (ScoreDoc scoreDoc : scoreDocs) { int docId = scoreDoc.doc; Document document = indexSearcher.doc(docId); System.out.println("Content: " + document.get("content")); } // 关闭索引读取器 indexReader.close(); } catch (IOException | ParseException e) { e.printStackTrace(); } } } ``` 以上示例演示了如何使用Lucene创建索引并进行搜索。在创建索引时,需要定义分词器、索引配置、文档字段等。在搜索索引时,需要创建查询解析器、执行查询并获取结果。你可以根据自己的需求进行更多的定制和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值