Lucene学习笔记

师兄推荐我学习Lucene这门技术,用了两天时间,大概整理了一下相关知识点。

一、什么是Lucene

Lucene即全文检索。全文检索是计算机程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置。当用户查询时根据建立的索引查找,类似于通过字典的检索字表查字的过程。

二、Lucece全文检索和数据库检索的区别

三、Lucene的原理

(1)索引库操作原理

注意:这里面有两个关键的对象:分别是IndexWriter和IndexSearcher。

执行增删改操作用的是IndexWriter对象,执行查询操作用的是IndexSearcher对象。

(2)索引库存放数据原理

 

注意:Lucece库在4.0之前和4.0之后的API发生了很大变化,这个图中的Index到后面的API已经不建议再用了。后面有相应的替代方法。

比如:原来的写法:

String id = NumericUtils.intToPrefixCoded(1);

new Field("id",id,Store.YES,Index.NOT_ANALYZED);

new Field("title", "我是陈驰",Store.YES, Index.NOT_ANALYZED);

new Field(""content",
    "国防科学技术大学(National University of Defense Technology),是中华人民共和国中央军事委员会直属的一所涵盖理学、工学、军事学、管理学、经济学、哲学、文学、教育学、法学、历史学等十大学科门类的综合性全国重点大学",

Store.YES,

Index.ANALYZED);

后来的写法:

new IntField("id", 1, Store.YES);

new StringField("title", "我是陈驰", Store.YES);

new TextField(
    "content",
    "国防科学技术大学(National University of Defense Technology),是中华人民共和国中央军事委员会直属的一所涵盖理学、工学、军事学、管理学、经济学、哲学、文学、教育学、法学、历史学等十大学科门类的综合性全国重点大学",
    Store.YES);

四、Lucene开发原理(索引库与数据库同步)

数据库与索引库中存放相同的数据,可以使用数据库中存放的ID用来表示和区分同一条数据。

--数据库中用来存放数据

--索引库中用来查询、检索

检索库支持查询检索多种方式,

特点:

1:由于是索引查询(通过索引查询数据),检索速度快,搜索的结果更加准确

2:生成文本摘要,摘要截取搜索的文字出现最多的地方

3:显示查询的文字高亮

4:分词查询等

注意:添加了索引库,并不意味着不往数据库中存放数据,数据库的所有操作仍和以前一样。只不过现在多维护一个索引库,在查询的时候可以提高效率。

索引库中存放的数据要转换成Document对象(每条数据就是一个Document对象),并向Document对象中存放Field对象(每条数据对应的字段,例如主键ID、所属单位、图纸类别、文件名称、备注等),将每个字段中的值都存放到Field对象中。

五、开发步骤

(1)需要的jar包

(2)需要的配置文件(注:这里我用的是IKAnalyzer,是第三方的中文分词器,庖丁分词,中文分词,特点:扩展新的词,自定义停用词。只有用该分词器才用到以下配置文件。)

l  IKAnalyzer.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <comment>IK Analyzer 扩展配置</comment>
    <!--用户可以在这里配置自己的扩展字典-->
    <entry key="ext_dict">mydict.dic;</entry> 

     <!--用户可以在这里配置自己的扩展停止词字典-->
    <entry key="ext_stopwords">ext_stopword.dic</entry>
</properties>

l  ext.dic(扩展词库)

l  stopword.dic(停用词库)

(3)一个简单的例子(用的标准分词器StandardAnalyzer,所以暂时没有用到上面的配置文件,标准分词器是汉字一个一个分的,英语还是按单词)

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.IntField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;

/**
 * 使用lucene对数据创建索引
 *
 * @author chenchi
 *
 */
public class TestLucene {

    /**
     * 使用IndexWriter对数据创建索引
     * @throws IOException
     */
    @Test
    public void testCreateIndex() throws IOException {
        // 索引存放的位置...
        Directory d = FSDirectory.open(new File("indexDir/"));

        // 索引写入的配置
        Version matchVersion = Version.LUCENE_CURRENT;// lucene当前匹配的版本
        Analyzer analyzer = new StandardAnalyzer(matchVersion);// 分词器
        IndexWriterConfig conf = new IndexWriterConfig(matchVersion, analyzer);
        // 构建用于操作索引的类
        IndexWriter indexWriter = new IndexWriter(d, conf);

        // 通过IndexWriter来创建索引
        // 索引库里面的数据 要遵守一定的结构(索引结构,document)
        Document doc = new Document();
        /**
         * 1.字段的名称 2.该字段的值 3.字段在数据库中是否存储
         * StringField是一体的
         * TextField是可分的
         */
        IndexableField field = new IntField("id", 1, Store.YES);
        IndexableField title = new StringField("title", "java培训零基础开始 从入门到精通",
                Store.YES);
        IndexableField content = new TextField(
                "content",
                "java培训,中软国际独创实训模式,三免一终身,学java多项保障让您无后顾之忧。中软国际java培训,全日制教学,真实项目实战,名企定制培训,四个月速成java工程师!",
                Store.YES);

        doc.add(field);
        doc.add(title);
        doc.add(content);
        // document里面也有很多字段
        indexWriter.addDocument(doc);

        indexWriter.close();
    }

    /**
     * 使用IndexSearcher对数据创建索引
     *
     * @throws IOException
     */
    @Test
    public void testSearcher() throws IOException {
        // 索引存放的位置...
        Directory d = FSDirectory.open(new File("indexDir/"));

        // 通过indexSearcher去检索索引目录
        IndexReader indexReader = DirectoryReader.open(d);
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);

        // 这是一个搜索条件,根据这个搜索条件我们来进行查找
        // term是根据哪个字段进行检索,以及字段对应值
        //================================================
        //注意:这样是查询不出,只有单字才能查询出来
        Query query = new TermQuery(new Term("content", "培训"));

        // 搜索先搜索索引目录
        // 找到符合条件的前100条数据
        TopDocs topDocs = indexSearcher.search(query, 100);
        System.out.println("总记录数:" + topDocs.totalHits);
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        for (ScoreDoc scoreDoc : scoreDocs) {
            //得分采用的是VSM算法
            System.out.println("相关度得分:" + scoreDoc.score);
            //获取查询结果的文档的惟一编号,只有获取惟一编号,才能获取该编号对应的数据
            int doc = scoreDoc.doc;
            //使用编号,获取真正的数据
            Document document = indexSearcher.doc(doc);
            System.out.println(document.get("id"));
            System.out.println(document.get("title"));
            System.out.println(document.get("content"));
        }
    }

}

(4)实现Lucene的CURD操作

先写一个LuceneUtils类:

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.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

public class LuceneUtils {

    public static Directory d = null;
    public static IndexWriterConfig conf = null;
    public static Version matchVersion = null;
    public static Analyzer analyzer = null;

    static{
        try {
            d = FSDirectory.open(new File(Constant.FILEURL));
            matchVersion = Version.LUCENE_44;
            //注意:该分词器是单字分词
            analyzer = new StandardAnalyzer(matchVersion);

            conf = new IndexWriterConfig(matchVersion, analyzer);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     *
     * @return 返回版本信息
     */
    public static Version getMatchVersion() {
        return matchVersion;
    }

    /**
     *
     * @return 返回分词器
     */
    public static Analyzer getAnalyzer() {
        return analyzer;
    }

    /**
     *
     * @return 返回用于操作索引的对象
     * @throws IOException
     */
    public static IndexWriter getIndexWriter() throws IOException{
        IndexWriter indexWriter = new IndexWriter(d, conf);
        return indexWriter;
    }

    /**
     *
     * @return 返回用于读取索引的对象
     * @throws IOException
     */
    public static IndexSearcher getIndexSearcher() throws IOException{
        IndexReader r = DirectoryReader.open(d);
        IndexSearcher indexSearcher = new IndexSearcher(r);
        return indexSearcher;
    }
}
时间: 2024-12-21 03:09:16

Lucene学习笔记的相关文章

lucene学习笔记(三)

好几天没更新了.更新一下,方便自己和大家学习. 这是最基本的代码 package index; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document;

lucene学习笔记(二)

package index; import java.io.File; 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.CorruptIn

Lucene学习笔记(1)

下载:http://lucene.apache.org lucene项目的Java子项目:http://lucene.apache.org/java Lucene学习笔记 查询者输入查询条件,条件之间可以通过特定运算符进行运算,比如查询希望查询到与“中国”和“北京”相关的记录,但不希望结果中包括“海淀区中关村”,于是输入条件为“中国+北京-海淀区中关村”: 把IndexWriter想象成让你可以对索引进行写操作的对象. 在一个文档被索引之前,首先需要对文档内容进行分词处理,并且而剔除一些冗余的词

Lucene学习笔记: 五,Lucene搜索过程解析

一.Lucene搜索过程总论 搜索的过程总的来说就是将词典及倒排表信息从索引中读出来,根据用户输入的查询语句合并倒排表,得到结果文档集并对文档进行打分的过程. 其可用如下图示: 总共包括以下几个过程: IndexReader打开索引文件,读取并打开指向索引文件的流. 用户输入查询语句 将查询语句转换为查询对象Query对象树 构造Weight对象树,用于计算词的权重Term Weight,也即计算打分公式中与仅与搜索语句相关与文档无关的部分(红色部分). 构造Scorer对象树,用于计算打分(T

Lucene学习笔记(一)

一.什么是lucene 官方的理解:全文检索首先是将要查询的目标文档中的词提取出来,组成索引,通过查询索引达到搜索目标文档的目的,这种先建立索引,在根据索引搜索文档的过程叫做全文检索 自身理解:也就类似于使用字典的过程,而索引就是字典的索引目录,方便我们来查询汉字. Lucene是什么:Lucene是appache下的一个开源全文检索的引擎工具包,通过这个简单易用的工具包,可以快速开发全文检索应用. 全文检索应用:搜索引擎(例如:百度,谷歌).站内搜索(京东的商品搜索).文件搜索等. Lucen

lucene学习笔记二(基于数组的lucene检索,索引删除)

构建数组: private String[] ids = {"1","2","3","4","5","6"}; private String[] emails = {"[email protected]","[email protected]","[email protected]","[email protected

lucene学习笔记(一)

package l002; 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.StringFi

lucene学习笔记四(分页查询)

/**  * 根据页码和分页大小获取上一次最后一个ScoreDoc  * @param pageIndex  * @param pageSize  * @param query  * @param indexSearcher  * @return  * @throws IOException  */ private ScoreDoc getLastScoreDoc(int pageIndex,int pageSize,Query query,IndexSearcher indexSearcher

Hadoop学习笔记_2_Hadoop源起与体系概述[续]

Hadoop源起与体系概述 Hadoop的源起--Lucene Lucene是Doug Cutting开创的开源软件,用java书写代码,实现与Google类似的全文搜索功能,它提供了全文检索引擎的架构,包括完整的查询引擎和索引引擎 早期发布在个人网站和SourceForge,2001年年底成为apache软件基金会jakarta的一个子项目 Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎 对于大数据的