lucene实例与源码解析

作者: Tim在路上 | 来源:发表于2019-05-07 21:35 被阅读1次

    lucene是什么?

    全文检索的引擎工具包,实现了全文检索的类库。
    全文检索,将查询的目标对象提取出来构造一套索引,查询索引得到数据结果。

    lucene有什么用?怎么用?

    lucene的使用非常简单,构建索引,查询
    主要作用是电商平台的搜索。

    1. 构造索引:(文件系统/数据库/网上数据/)->初始化lucene可以实现的对象->分析文档对象(分词,分析)->创建索引。

    2. 搜索索引获取目标文档:用户通过界面输入查询对象->创建查询索引->去搜索库查询->渲染结果

    lucene开发搭建

    开发思路:

    1. 构建索引

    将原始数据放入到lucene的document对象,
    并设置好对象。

    将document进行分析(分词)

    域的三个属性,分词,索引,存储

     document.add(new TextField(FIELD,"hello world", Field.Store.YES));
     document.add(new StoredField(FIELD,"hello china"));
    

    TextField 模型进行分词,Field.Store.YES 表示进行存储(即可以提供返回结果)
    Field.Store.NO 表示不进行存储 (表示进行分词作为索引,但不存储提供返回结果)
    new StoredField(FIELD,"hello china") 指的是只提供存储

    1. 将document进行分词,得到索引

    analyzer 分词器,中文分词器

    创建索引目录,创建构造索引的配置对象

    indexWriter构造索引

    1. 创建查询对象

    2. 执行搜索,指定索引目录

    实例代码

    本实例代码使用的是lucene8.0.0,jdk 8
    使用maven配置的项目,maven配置见下

    public class LuceneIndex {
    
        //创建索引存储位置
        private static final String INDEX_LOCATION = "/opt/project-get/luceneDemo/lucene";
        //设置lucene域名
        private static final String FIELD = "content";
    
    
        public static void index() throws IOException {
            //这里注意lucene8.0.0    FSDirectory.open() 内的参数是path类型
    
            // 打开lucene的存储目录
            Directory dirLucene = FSDirectory.open(Paths.get(INDEX_LOCATION));
    
            // 构建索引
            //注意这里一定要进行配置分词器,默认的分词器是按照英文设置的,这里采用的版本号默认是8.0.0
            IndexWriterConfig config = new IndexWriterConfig(new StandardAnalyzer());
            IndexWriter indexWriter = new IndexWriter(dirLucene,config);
    
    
            //创建文档
            Document document = new Document();
            //向文档中添加域
            document.add(new TextField(FIELD,"hello world", Field.Store.YES));
    
            Document document1 = new Document();
            document1.add(new StoredField(FIELD,"hello china"));
    
            Document document2 = new Document();
            document2.add(new TextField(FIELD," I love you", Field.Store.YES));
    
            Document document3 = new Document();
            document3.add(new TextField(FIELD,"hello zhao ", Field.Store.NO));
    
            //将文档添加到本地索引中
            indexWriter.addDocument(document);
            indexWriter.addDocument(document1);
            indexWriter.addDocument(document2);
            indexWriter.addDocument(document3);
    
            indexWriter.commit();
            indexWriter.close();
        }
    
        public static  void search(String item) throws IOException{
            //获取lucene本地存储路径
            Directory dir = FSDirectory.open(Paths.get(INDEX_LOCATION));
            //获取索引读取器
            IndexReader indexReader = DirectoryReader.open(dir);
            IndexSearcher indexSearcher = new IndexSearcher(indexReader);
    
            //读取查询关键词
            TermQuery query = new TermQuery(new Term(FIELD,item));
            //获取前10返回结果
            TopDocs topN = indexSearcher.search(query,10);
    
            for(int i=0;i < topN.totalHits.value; i++){
                Document doc = indexSearcher.doc(topN.scoreDocs[i].doc);
    
                System.out.println("doc"+i+":\""+doc.get(FIELD)+"\"");
                System.out.println("score: " + topN.scoreDocs[i].score + "\"");
            }
        }
    
        public static void main(String[] args) throws IOException {
            //索引只用创建一次
            index();
            
            search("world");
        }
    
    }
    

    结果:

    doc0:"hello world"
    score: 0.49705765"
    

    最后的分数是,lucene使用布尔和VSM两个模型的结合,来进行搜索关键词与文档的打分操作,判断文档与关键词的相似性和相关性。

     <dependencies>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-core</artifactId>
            <version>8.0.0</version>
        </dependency>
    
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-highlighter</artifactId>
            <version>8.0.0</version>
        </dependency>
    
        <!-- http://mvnrepository.com/artifact/org.apache.lucene/lucene-analyzers-common -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-analyzers-common</artifactId>
            <version>8.0.0</version>
        </dependency>
    
        <!-- http://mvnrepository.com/artifact/org.apache.lucene/lucene-memory -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-memory</artifactId>
            <version>8.0.0</version>
        </dependency>
    
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    
        <!-- http://mvnrepository.com/artifact/org.apache.lucene/lucene-queryparser -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-queryparser</artifactId>
            <version>8.0.0</version>
        </dependency>
    

    分析程序

    目前搜索引擎采取的处理大量查询数据的思路都是,事先把跟关键词相匹配数据存储起来,查找的时候直接把存储好的数据进行返回。

    在我们指定的索引存储位置处生成了几个文件:

    _0.cfe      索引信息的合成文件,仅仅作为减少索引读取时文件句柄的数量,提高性
    能之用。
    _0.cfs      索引信息的合成文件,仅仅作为减少索引读取时文件句柄的数量,提高性
    能之用。
    _0.si       段(Segment)文件,存储着一个段的元信息
    segments_1  全局性文件,保存着索引的提交点(commit point)信息。在一个完整的索引结构中两个文件各有一个
    write.lock  生成索引时保护索引结构的文件,
    

    进行存储的就是内容分词后的词和对应的文档关系。

    在lucene中的索引,被称作“反向索引”或者是“倒排索引”,称作反向主要是因为,在关系型数据库中我们一般将id作为索引,内容作为查询存储结果,在lucene中则是将内容分词后的结果作为索引,将id作为索引的结果进行返回。

    然后再通过id进行查询,返回内容信息。

    lucene的检索模型

    lucene使用两个模型的结合,来进行搜索关键词与文档的打分操作。

    1. 布尔模型
    布尔模型,搜索过程就是判断文档与用户意图是否相关的一个过程,是逻辑运算(也称布尔运算)的过程

    对于一个用户输入的关键词,搜索引擎要布尔运算判断每篇文献是否含有这个关键词,如果含有关键词,则给这篇文章一个逻辑值——真(TRUE 或 1),否则,给它一个逻辑值——假(FALSE 或 0)。

    1. VSM模型
    是一种代数模型。该模型主要用于解决文本相似度的问题,搜索关键词与对应网页相似度可以视为文本相似度的问题。

    模型基于这样一种假设:文档中词与词是相互独立,豪无关联的个体(又称”词袋模型”)

    对于一个词汇量为 N
    的文档集 ,其中每一篇文档都是一个 N 维的向量;词汇表中的每一个词的 ID 对应着向量中
    的一个位置,词的权重为向量位置上的值。如果文档中没有该词,那么该位置上的值为 0 。

    VSM 模型用 TF-IDF 来度量词的权重。
    TF(Term Frequency):文档中的词频。
    DF(Document Frequency):文档集中含该词的文档份数。
    IDF(Inverse Document Frequency) = log10(N/DF) ; N 表示文档集中文档的总数。

    Lucene 的数据模型

    整个lucene文件的数据文件结构有:

    Lucene 中可搜索的实体都表现为文档(document),它由字段(field)和值(value)组成。每个字段值都由一个或多个可搜索的元素——词汇(term)。一个或者多个文档(document)构成索引中的段(segment);一个或者多个段(Segment)构成一个完整的索引数据集。

    相关文章

      网友评论

        本文标题:lucene实例与源码解析

        本文链接:https://www.haomeiwen.com/subject/enruoqtx.html