全文检索及lucene学习笔记

之前看过也部署过ES,但和MQ一样,认识的很浅导致现在也没什么印象,所以这里也从全文检索开始了解和学习.

全文检索的概念:

全文检索是指以文本作为检索对象,找出含有指定词汇的文本。全面、准确和快速是衡量全文检索系统的关键指标。

关于全文检索,我们要知道:1,只处理文本。2,不处理语义。3,搜索时英文不区分大小写。4,结果列表有相关度排序。5,并且可以对结果具有过滤高亮的功能
原文地址: 原文地址

lucene:

lucene是是apche下的一个全文检索工具, solr和ES都是基于lucene的原理开发的, 类似于jdbc和Mybatis的关系.

lucene的使用场景:

站内搜索: 如taobao,jd,站内贴吧搜索等.
互联网搜索: baidu,google, biying等搜索引擎

常见的搜索算法:

顺序扫描法:
描述: 拿着关键字逐条比较,逐字匹配,找到为止.
缺点: 随着内容的大量增长而效率逐渐降低.
优点: 准确率高.
举例:数据库中的like查询.

倒排索引算法:
描述:把数据库中的所有内容查询出来,然后进行切分词(把内容中的:的,得,地,a,an,the等不重要的词删掉,大写变小写,空格去掉.剩下词就是分词),将分出来的词组成索引(目录),把查询出来的内容存入文档中,索引和文档组成索引库( 索引 + 文档,就是电脑上的一个文件夹,其中存储了索引和文档). 在检索时,先找到索引,索引和文档之间有联系,能快速地确定文档的内容,返回数据.
优点: 效率高,不会随着数据大量增长而效率逐渐降低.
缺点: 需要定时针对索引库进行更新,以空间换时间,索引库占用电脑大量的空间.
举例:新华字典,当我们看到一个不认识的字的时候,会通过偏旁(索引)查询该字,而该字后面有页码(索引和文档的联系),通过页码找到该字地详细信息(文档).

lucene的原理:

倒排索引算法思路:
文档; 是lucene中的一个对象, 一个文档对应表里的一条数据.,每条数据中的每一列对应一个域对象.

在这里插入图片描述

从图中可以看到,lucene会将数据全部查询出来,进行分词,切分词后组成索引,然后将内容放入文档当中,将数据每一个字段值放到域对象中,域对象放入文档,文档 +索引 组成索引库.

lucene的使用:

创建索引库:
1.创建分词对象:

  //1.创建分词对象:

        Analyzer analyzer = new StandardAnalyzer();

2.准备数据 —jdbc

  //2.准备数据 ---jdbc,从数据库查询数据
        BookDao bookDao= new  BookDao();

        List<Book> bookList = bookDao.findAll();

3.创建文档列表对象 ---- 一个book对象对应一个文档
4.创建域对象 ---- 一个book对象中的属性对应一个域对象

  //3.创建文档列表对象  ----  一个book对象对应一个文档
        //文档集合
        List<Document> docList = new ArrayList<Document>();
        for (Book book : bookList) {
            //一个book 一个文档
            //创建文档
            Document doc = new Document();

            //4.创建域对象   ----  一个book对象中的属性对应一个域对象
            //id
            TextField idFiled = new TextField("id",String.valueOf(book.getId()), Field.Store.YES);    //param1: 域名(列名称)   param2:域值(数据值)  param3: 是否存储
            //name
            TextField nameFiled = new TextField("name",book.getName(), Field.Store.YES);    //param1: 域名(列名称)   param2:域值(数据值)  param3: 是否存储
            //price
            TextField priceFiled = new TextField("price",String.valueOf(book.getPrice()), Field.Store.YES);    //param1: 域名(列名称)   param2:域值(数据值)  param3: 是否存储
            //description
            TextField descFiled = new TextField("description",book.getDescription(), Field.Store.YES);    //param1: 域名(列名称)   param2:域值(数据值)  param3: 是否存储
            //pic
            TextField picFiled = new TextField("pic",book.getPic(), Field.Store.YES);    //param1: 域名(列名称)   param2:域值(数据值)  param3: 是否存储

            //把域对象添加到文档对象中
            doc.add(idFiled);
            doc.add(nameFiled);
            doc.add(priceFiled);
            doc.add(descFiled);
            doc.add(picFiled);
            //将文档对象添加到文档集合中
            docList.add(doc);

        }

5.指定索引库的位置

  //5.指定索引库的位置

        FSDirectory dir = FSDirectory.open(new File("D:\\es"));

        //创建索引输出流配置对象
        //param1  版本号  param2: 分词器对象
        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_4_10_3,analyzer);

6.创建索引输出流对象

  //6.创建索引输出流对象
        //param1: 索引库位置对象  param2: 索引输出流配置对象
        IndexWriter  indexWriter = new IndexWriter(dir,indexWriterConfig);

        //把文档对象写入到索引库中
        for (Document document : docList) {
            indexWriter.addDocument(document);
        }


        //提交
        indexWriter.commit();
        //释放资源
        indexWriter.close();

Dao层代码各位自行写,就是一个简单的查询sql,启动后报如下错误.
在这里插入图片描述
检查了一下包,发现根本没有lucene50这个包,怀疑是否是版本问题,于是换成了5.0.0版本
在这里插入图片描述

启动后发现50变成53了…
在这里插入图片描述
在这里插入图片描述

后来排查后发现是依赖冲突的问题,因为是学ES写了几个demo,导入了ES相关的包导致的,将ES的依赖删除即可启动成功了

成功后找到对应目录发现多了几个文件:
在这里插入图片描述

lucene图形化界面:

使用lukeall的jar包:
在这里插入图片描述

运行命令: java -jar lukeall-4.10.3.jar

在这里插入图片描述

打开刚刚lucene存储数据的目录即可看到存的数据了:
索引界面.
在这里插入图片描述

文档界面:
在这里插入图片描述
搜索页面:

在这里插入图片描述

搜索页面我们可以看到查出来的数据有score一列,分数越高排行越靠前,分数是经过一定算法算出数据和查询需求的匹配度,匹配度越高分数越高.

其他页面就不一一说了,大家可以自己研究.

lucene的查询操作:

需要注意一点: 创建索引库和查询(删除,修改)索引库使用的分词对象必须是同一个.

直接贴代码吧:

package com.ceeemall.es.demo;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryparser.classic.ParseException;
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.FSDirectory;
import org.junit.Test;

import java.io.File;
import java.io.IOException;

public class SearchDemo {

    @Test
    public void searchTest() throws IOException, ParseException {

        //创建分词器
        Analyzer analyzer = new StandardAnalyzer();
        //指定索引位置
        FSDirectory dir = FSDirectory.open(new File("D:\\es\\dic"));
        //输入流对象
        IndexReader indexReader = IndexReader.open(dir);

        //索引的查询对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);

        //创建查询分析对象
        //param1: 默认的域名(如果查询时指定了域则在指定域中查询,否则使用默认域)  param2: 分词器对象
        QueryParser queryParser  =new QueryParser("name",analyzer);
        //获取查询关键字对象
        Query query = queryParser.parse("java");
        //检索
        //param1: query 查询的关键字对象   param2: 最多查询的条数
        //return:最上面的文档
        TopDocs topdocs = indexSearcher.search(query, 2);
        //返回分数文档
        ScoreDoc[] scoreDocs = topdocs.scoreDocs;
        //遍历
        for (ScoreDoc scoreDoc : scoreDocs) {
            //文档索引
            int docId = scoreDoc.doc;
            //获取文档对象
            Document document = indexSearcher.doc(docId);
            String id = document.get("id");
            String name = document.get("name");
            String description = document.get("description");
            String price = document.get("price");
            String pic = document.get("pic");

            System.out.println(id + " " + name + " " + description + " " + price + " " + pic );
        }



    }
}

从索引中查询出数据:
在这里插入图片描述

删除更新就不写了,大家可以自己研究.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值