1、lucene入门(lucene笔记)

一、概述

lucene是一个全文搜索引擎,在全文索引工具中,都是由这样的但部分组成:

  • 1、索引部分
  • 2、分词部分
  • 3、搜索部分

二、入门程序

2.1 入门程序

这里我们需要导入lucenejar包,注意:这里使用的是3.5.0版本,lucene的各个版本差异较大。
下面看入门程序,看lucene如何创建索引和搜索索引(工程lucene01):
HelloLucene.java

package cn.lucene.test;
import java.io.File;
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.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
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.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;

public class HelloLucene {
    
    //建立索引
    public void index(){
        IndexWriter writer = null;
        try {
            //1、创建Directory
            //Directory directory = new RAMDirectory();//索引是建立在内存中的
            Directory directory = FSDirectory.open(new File("E:/myeclipse/Lucene/index"));//创建在硬盘上
            
            //2、创建IndexWriter
            IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35));
            writer = new IndexWriter(directory, iwc);
            
            //3、创建Document对象
            Document doc = null; 
                    
            //4、为Document添加Field,是Document的一个子元素
            File file = new File("E:/myeclipse/Lucene/somefile");
            for(File f : file.listFiles()){
                doc = new Document();
                doc.add(new Field("content", new FileReader(f)));
                doc.add(new Field("filename", f.getName(), Field.Store.YES, Field.Index.NOT_ANALYZED));
                doc.add(new Field("path", f.getAbsolutePath(), Field.Store.YES, Field.Index.NOT_ANALYZED));
                //5、通过IndexWriter添加文档到索引中
                writer.addDocument(doc);
            }
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (LockObtainFailedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(writer != null){
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    //搜索
    public void search(){
        Directory directory;
        try {
            //1、创建Directory
            directory = FSDirectory.open(new File("E:/myeclipse/Lucene/index"));
            
            //2、创建IndexReader
            IndexReader reader = IndexReader.open(directory);
            //3、根据IndexReader创建IndexSearcher
            IndexSearcher searcher = new IndexSearcher(reader);
            //4、创建搜索的Query
            //创建QueryParser来确定要搜索文件的内容,第二个参数表示搜索的域
            QueryParser parser = new QueryParser(Version.LUCENE_35, "content", new StandardAnalyzer(Version.LUCENE_35));
            //创建Query,表示搜索域为content中包含java的文档
            Query query = parser.parse("java");
            //5、根据searcher搜索并且返回TopDocs
            TopDocs tdoc = searcher.search(query, 10);//只会显示10条内容
            
            //6、根据TopDocs获取ScoreDoc对象
            ScoreDoc sdocs[] = tdoc.scoreDocs;
            for(ScoreDoc s : sdocs){
                //7、根据searcher行业ScoreDoc获取具体的Document对象
                Document document = searcher.doc(s.doc);
                //8、根据Document对象获取所需要的值
                System.out.println(document.get("filename") + "[" + document.get("path") + "]");
            }
            //9、关闭reader
            reader.close(); 
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

说明:这里我们存储的文档放在E:/myeclipse/Lucene/somefile中,创建的搜索我们放在E:/myeclipse/Lucene/index中,这里方法index()是创建文档索引的方法,而search()是搜索文档索引的方法。

2.2 测试

TestLucene.java

package cn.lucene.test;
import org.junit.Test;
public class TestLucene {
    
    @Test
    public void testIndex(){
        HelloLucene hLucene = new HelloLucene();
        hLucene.index();
    }
    
    @Test
    public void testSearch(){
        HelloLucene hLucene = new HelloLucene();
        hLucene.search();
    }
}

说明:这里我们在创建文档之后再次创建生成的索引不会覆盖,而是会增加,这是因为lucene索引是一种增量索引,每次生成索引都不会将前面生成的索引删除,而是添加,于是每次搜索出来的结果会有重复。这里我们搜索关键字为java,会打印出相关的文件路径,这里我们先不深究程序的具体实现。

三、相关概念

3.1 建立索引时最重要的几个术语

  • Document:一个要进行索引的单元,相当于数据库的一行纪录,任何想要被索引的数据,都必须转化为Document对象存放。

  • FieldDocument中的一个字段,相当于数据库中的ColumnFieldlucene比较多概念一个术语。

  • IndexWriter:负责将Document写入索引文件。通常情况下,IndexWriter的构造函数包括了以下3个参数:索引存放的路径,分析器和是否重新创建索引。特别注意的一点,当IndexWriter执行完addDocument方法后,一定要记得调用自身的close方法来关闭它。只有在调用了close方法后,索引器才会将存放在内在中的所有内容写入磁盘并关闭输出流。

  • Analyzer:分析器,主要用于文本分词(可以这样理解,就是将一段话分成单个的词语,然后为单个的词语建立标识,便于搜索,就像一个超链接一样)。常用的有StandardAnalyzer分析器,StopAnalyzer分析器,WhitespaceAnalyzer分析器等。

  • Directory:索引存放的位置。lucene提供了两种索引存放的位置,一种是磁盘,一种是内存。一般情况将索引放在磁盘上;相应地lucene提供了FSDirectoryRAMDirectory两个类。

  • 段:SegmentLucene索引文件的最基本的一个单位。Lucene说到底就是不断加入新的Segment,然后按一定的规则算法合并不同的Segment以合成新的Segment。我们在上面测试时从建立的索引文件中就可以看出有如

    1

    图中使用0,1标号表示的就是段,而这里我们可以看到每次创建索引都是增加而不是覆盖。

  • 最后lucene建立索引的过程就是将待索引的对象转化为LuceneDocument对象,使用IndexWriter将其写入lucene 自定义格式的索引文件中。待索引的对象可以来自文件、数据库等任意途径,用户自行编码遍历目录读取文件或者查询数据库表取得ResultSetLuceneAPI只负责和字符串打交道。

3.2 存储域选项

存储域选项有Field.Store.YESField.Store.NO,设置为YES表示把这个域中的内容完全存储到文件中,方便进行文本的还原,设置为NO表示不把这个域中的内容完全存储到文件中,但是可以被索引,此时内容无法完全还原。比如一篇文章,我们可以建立文章的索引(此索引就是用来搜索这篇文章的一个标签),但是我们可以不将整片文章内容全部存储下来,但是这样我们虽然能搜索到这篇文章,但是却不能将其还原。

3.3 索引域选项:

  • Field.Index.ANALYZED:进行分词和索引,适用于标题、内容等。
  • Field.Index. ANALYZED_NO_NORMS:进行分词但是不存储norms信息,这个norms中包括创建索引的时间和权值等信息
  • Field.Index. NOT_ANALYZED:进行索引,但是不进行分词,如身份证号、姓名、ID等,试用于精确索引
  • Field.Index. NOT_ANALYZED_NO_NORMS:即不进行分词也不存储norms信息
  • Field.Index.NO:不进行索引

3.4 最佳实践

域选项 存储与否 最佳实践
NOT_ANALYZED_NO_NORMS YES 标识符(主键、文件名),电话号码,身份证号,姓名,日期
ANALYZED YES 文档标题和摘要
ANALYZED NO 文档正文
NO YES 文档类型,数据库主键(不进行索引)
NOT_ANALYZED NO 隐藏关键字
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,612评论 5 471
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,345评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,625评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,022评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,974评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,227评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,688评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,358评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,490评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,402评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,446评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,126评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,721评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,802评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,013评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,504评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,080评论 2 341

推荐阅读更多精彩内容

  • 也是项目需要用的框架之一,为了不让自己轻易忘记它,在此记录一系列的lucene学习笔记(基于lucene4.4,I...
    JackFrost_fuzhu阅读 1,989评论 4 27
  • 目录结构:1.全文检索 2.Lucene入门3.Lucene进阶 全文检索 一, 生活中的搜索:1.Win...
    CoderZS阅读 1,640评论 0 12
  • 构建索引过程 文档是Lucene索引和被搜索的最小单位,一个文档包含一个或者多个域,而域则包含了真正 被搜索 的内...
    RagPanda阅读 3,443评论 0 2
  • 雨 滴滴答答猛下着 一个女孩雨幕中 湿透了 雨伞漏洞了 我冲过去 把雨伞遮住她的身子 撞到了一把伞 一个女人跟我面...
    小草_d5ad阅读 241评论 12 24
  • 可以向我具体描述一下你明年的期待吗? 通过运动等方式,使身体各项指标正常 这些期待对于你来说为什么这么重要? 1....
    右手戒指阅读 222评论 0 0