Lucene3.6入门实例

jopen 10年前

一、简介
Lucene是什么:Lucene是apache软件基金会jakarta 项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引 引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的 功能,或者是以此为基础建立起完整的全文检索引擎。

Lucene是一个基于Java的全文搜索,不是一个完整的搜索应用,而是 一个代码库和API,可以方便地为应用提供搜索功能。 实际上Lucene的功能就是将开发人员提供的若干个字符串建立索引,然后提供一个全文搜索服务,用户将搜索的关键词提供给搜索服务,搜索服务告诉用户关 键词出现的各字符串。

 

二、基本流程

lucene包含两部分:建立索引和搜索服务。建立索引是将源(本质是字符串)写入索引或者将源从索引中删除;进行搜索是向用户提供全文搜索服务,用户可以通过关键词定位源。

1、建立索引的流程
使用analyzer处理源字符串,包括:分词,即分成一个个单词;去除stopword(可选)。
将源中的有效信息以不同Field的形式加入Document中,并把Document加入索引,从而在索引中记录有效的Field。

将索引写入存储器(内存或磁盘)。

 

2、检索的流程
用户提供搜索关键词,经过analyzer处理。
对处理后的关键词搜索索引找出对应的Document。
用户根据需要从找到的Document中提取需要的Field。 

三、基本概念
1. Analyzer
Analyzer的作用是分词,并去除字符串中的无效词语。
分词的目的是把字符串按某种语义规则划分为若干个词。英文中比较容易实现分词,因为英文本身就是以单词为单位,已经用空格分开;而中文则必须以某种方法将 连成一片的句子划分成一个个词。 无效词语,如英文中的“of”、“the”和中文中的“的”、“地”等,这些词语在文章中大量出现。但是本身不包含关键信息,去掉后有利于缩小索引文件、 提高命中率和执行效率。

2. Document
用户提供的源可以是文本文件、字符串或者数据库表中的一条记录等。一个源字符串经过索引之后,以一个Document的形式存储在索引文件中。搜索服务的结果也是以Document列表的形式返回。

3. Field
一个Document可以包含多个信息域,如一篇文章可以包含“标题”、“正文”、“最后修改时间”等信息域,这些信息域以Field的形式保存在Document中。
Field有两个属性:存储和索引。存储属性可以控制是否对这个Field进行存储;索引属性可以控制是否对该Field进行索引。这似乎多此一举,但事实上对这两个属性的正确组合很重要。 

下面举例说明:一篇文章需要对标题和正文进行全文搜索,所以把这两个Field的索引属性设置为真;同时希望能直接从搜索结果中提取文章标题,所以把标题 Field的存储属性设置为真。但是正文Field太大了,为了缩小索引文件,将正文Field的存储属性设置为假,需要访问时再直接读取文件正文;希望 能从搜索结果中提取最后修改时间;但是不需要对它进行搜索,所以把最后修改时间Field的存储属性设置为真,索引属性设置为假。
Field的两个属性禁止全为假的情况因为这对建立索引没有意义。

4. Segment

建立索引时,并不是每个document都马上添加到同一个索引文件,它们首先被写入到不同的小文件,然后再合并成一个大索引文件,每个小文件都是一个Segment。

5. Term
Term表示文档的一个词,是搜索的最小单位。Term由两部分组成:所表示的词语和这个词语所出现的field。

6. Token
Token是term的一次出现,它包含trem文本和相应的起止偏移,以及一个类型字符串。一句话中可以出现多次相同的词语,它们都用同一个term表示,但是用不同的token,每个token标记该词语出现的位置。 

四、Lucene的组成结构

Lucene包括core和sandbox两部分,其中core是 lucene的核心,sandbox包含了一些附加功能,如highlighter、各种分析器等。 Lucene core包含8个包:analysis、collation、document、index、queryParser、search、store、 util。

1. analysis包
Analysis提供自带的各种Analyzer,如按空白字符分词的WhitespaceAnalyzer,添加了stopword过滤的 StopAnalyzer,支持中文分词的SmartChineseAnalyzer,以及最常用的StandardAnalyzer。

2. collation包
包含collationKeyFilter和collationKeyAnalyzer两个相同功能的类,将所有token转换为 CollationKey,并将CollationKey与IndexableBinaryStringTools一起编码存储为一个term。

3. document包
document包中是Document相关的各种数据结构,如Document类、Field类等。

4. index包
index包中是索引的读写操作类,常用的是对索引文件的segment进行写、合并和优化的IndexWriter类和对索引进行读取和删除操作的 IndexReader类。IndexWriter只关心如何将索引写入一个个segment并将它们合并优化;IndexReader关注索引文件中 各个文档的组织形式。

5. queryParser包
queryParser包中是解析查询语句相关的类(常用的是QueryParser类)以及Token类。

6. search包

search包中是从索引中进行搜索的各种不同的Query类(如TermQuery、BooleanQuery等)和搜索结果集Hits类。

7. store包 store包中是索引的存储相关类,如Directory类定义了索引文件的存储结构,FSDirectory是存储在文件系统(即磁盘)中的索引存储 类,RAMDirectory为存储在内存中的索引存储类,MmapDirectory为使用内存映射的索引存储类。


8. util包 util包中是公共工具类,例如时间和字符串之间的转换工具。


五、环境搭建

使用Lucene3.6版本,到官网下载lucene-3.6.0.zip,解压。
需要用到的jar:
  \lucene-3.6.0\lucene-core-3.6.0.jar                      ------>      Lucene的核心包
  \lucene-3.6.0\contrib\analyzers\common\lucene-analyzers-3.6.0.jar    ------>      分词器
  \lucene-3.6.0\contrib\highlighter\lucene-highlighter-3.6.0.jar                ------>      高亮关键词使用
  \lucene-3.6.0\contrib\memory\lucene-memory-3.6.0.jar                     ------>      高亮关键词使用

Lucene3.6入门实例


六、示例代码

    package com.yulore.lucene;                import java.io.File;        import java.io.IOException;                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.document.Field.Index;        import org.apache.lucene.document.Field.Store;        import org.apache.lucene.index.CorruptIndexException;        import org.apache.lucene.index.IndexReader;        import org.apache.lucene.index.IndexWriter;        import org.apache.lucene.index.IndexWriterConfig;        import org.apache.lucene.queryParser.MultiFieldQueryParser;        import org.apache.lucene.queryParser.ParseException;        import org.apache.lucene.queryParser.QueryParser;        import org.apache.lucene.search.IndexSearcher;        import org.apache.lucene.search.Query;        import org.apache.lucene.search.ScoreDoc;        import org.apache.lucene.store.Directory;        import org.apache.lucene.store.FSDirectory;        import org.apache.lucene.store.LockObtainFailedException;        import org.apache.lucene.util.Version;        import org.wltea.analyzer.lucene.IKAnalyzer;                public class LuceneDemo02 {                    /**            * @param args            * @throws IOException             */            public static void main(String[] args) throws IOException {                                createIndex();                queryLucene("Lucene");            }                        /**            * 根据关键字搜索             * @param keyword            */            public static void queryLucene(String keyword){                try {                    File path = new File("D://LuceneEx");                    Directory mdDirectory = FSDirectory.open(path);                    Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_36);                                        IndexReader reader = IndexReader.open(mdDirectory);                                        IndexSearcher searcher = new IndexSearcher(reader);                            //          Term term = new Term("title", keyword);        //          Query query = new TermQuery(term);                    String[] fields = { "title","tag"};                    // (在多个Filed中搜索)                    QueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_36,                            fields, analyzer);                    Query query = queryParser.parse(keyword);                                        long start = System.currentTimeMillis();                                            ScoreDoc[] docs = searcher.search(query, null, 3).scoreDocs;                                        for(int i=0;docs!=null && i<docs.length;i++){                        Document doc = searcher.doc(docs[i].doc);                        int id = Integer.parseInt(doc.get("id"));                        String title = doc.get("title");                        String author = doc.get("author");                        String tag = doc.get("tag");                        String reputation = doc.get("reputation");                                                System.out.println(id+" "+title+" "+author+" "+tag+" "+reputation);                    }                                        reader.close();                    searcher.close();                                        long end = System.currentTimeMillis();                    System.out.println("queryLucene耗时:"+(end-start)+"ms");                                    } catch (CorruptIndexException e) {                    e.printStackTrace();                } catch (IOException e) {                    e.printStackTrace();                } catch (ParseException e) {                    e.printStackTrace();                }            }                        /**            * 创建索引            */            private static void createIndex(){                                try {                                        File path = new File("D://LuceneEx");                    Directory mdDirectory = FSDirectory.open(path);                                         // 使用Lucene提供的分词器          //          Analyzer mAnalyzer = new StandardAnalyzer(Version.LUCENE_36);                    // 使用 商业分词器                      Analyzer mAnalyzer = new IKAnalyzer();                      IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_36, mAnalyzer);                                        IndexWriter writer = new IndexWriter(mdDirectory, config);                                        long start = System.currentTimeMillis();                                        for(int i=0;i<10;i++){                                                Document doc = new Document();                                                Field id = new Field("id", "10000"+i, Store.YES, Index.ANALYZED);                        Field title = new Field("title", "Lucene开发入门"+i, Store.YES, Index.ANALYZED);                        Field author = new Field("author", "杨丰盛"+i, Store.YES, Index.ANALYZED);                        Field tag = new Field("tag", "Lucene、全文搜索"+i, Store.YES, Index.ANALYZED);                        Field reputation = new Field("reputation", "一本好书"+i, Store.YES, Index.ANALYZED);                                                doc.add(id);                        doc.add(title);                        doc.add(author);                        doc.add(tag);                        doc.add(reputation);                                                writer.addDocument(doc);                    }                                        writer.close();                                        long end = System.currentTimeMillis();                    System.out.println("createIndex耗时:"+(end-start)+"ms");                                    } catch (CorruptIndexException e) {                    e.printStackTrace();                } catch (LockObtainFailedException e) {                    e.printStackTrace();                } catch (IOException e) {                    e.printStackTrace();                }            }        }  
</div> </div>


参考http://www.cnblogs.com/bluepoint2009/archive/2012/09/25/introduction-to-lucene36.html