搜索引擎之Lucene

搜索引擎之Lucene

1.搜索引擎

1.1什么是搜索引擎

搜索引擎指的是通过一定的策略, 从互联网中获取到数据, 将这些数据保存到自己的服务器当中, 然后提供用户一个页面, 用来做查询的, 这个就被称为搜索引擎 例如: 百度 或者 谷歌

1.2 原始数据库查询的弊端
  • 当数据量很大的时候, 当用户输入一个内容的时候, 我们很难在很快的时间进行返回
  • 原始的数据库中模糊查询, 只能进行首尾的匹配
  • 当用户输入错误, 那么原始的数据库将会和用户的基本需求相差太远
1.3 倒排索引

倒排索引, 指定的将一句话,或者是一段话进行分词, 然后将分词的后的内容保存到索引库当中, 建立索引, 这样当用户输入一些内容的时候, 将用户输入的内容进行分词, 将分词后的数据到索引库中进行匹配, 如果有对应的数据将其对应的内容进行返回

2. lucene

lucene是Apache旗下的开源的全文检索的工具包, 使用lucene来构建一个搜索引擎

官方网址: http://lucene.apache.org/

2.1 lucene和solr的基本区别:

lucene: 是一个工具包

solr: 是基于lucene进行开发的一个企业级的搜索引擎

2.2 lucene的基本入门(索引库的创建)

2.2.1导包
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-core</artifactId>
                <version>4.10.2</version>
            </dependency>
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-queries</artifactId>
                <version>4.10.2</version>
            </dependency>
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-test-framework</artifactId>
                <version>4.10.2</version>
            </dependency>
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-analyzers-common</artifactId>
                <version>4.10.2</version>
            </dependency>
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-queryparser</artifactId>
                <version>4.10.2</version>
            </dependency>
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-highlighter</artifactId>
                <version>4.10.2</version>
            </dependency>
            <dependency>
                <groupId>com.janeluo</groupId>
                <artifactId>ikanalyzer</artifactId>
                <version>2012_u6</version>
            </dependency>
2.2.2添加索引的操作
 public void indexWriterToLucene() throws IOException {
    
            Directory directory = FSDirectory.open(new File("H:\\xx"));
            Analyzer analyzer = new StandardAnalyzer();
            IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LATEST,analyzer);
    
            IndexWriter indexWriter  = new IndexWriter(directory,indexWriterConfig);
  
            Document document =  new Document();
            document.add(new LongField("id",1L, Field.Store.YES));
            document.add(new TextField("content","welcome to beijing, how are you", Field.Store.YES));
            document.add(new StringField("title","今天天气很好", Field.Store.NO));
    
            indexWriter.addDocument(document);
    
            indexWriter.commit();
            indexWriter.close();
        }
    }

2.3 API详解

  • IndexWriter: 索引写入器对象,其主要的作用, 添加索引, 修改索引和删除索引
  • Directory: 目录类, 用来指定索引库的目录
    • 常用的实现类:
      • FSDirectory: 用来指定文件系统的目录, 将索引信息保存到磁盘上
        • 优点: 索引可以进行长期保存, 安全系数高
        • 缺点: 读取略慢
      • RAMDriectory: 内存目录, 将索引库信息存放到内存中
        • 优点: 读取速度快
        • 缺点: 不安全, 无法长期保存, 关机后就消失了
  • IndexWriterConfig: 索引写入器的配置类
    • 创建此对象, 需要传递Lucene的版本和分词器
    • 作用:
      • 作用1 : 指定Lucene的版本和需要使用的分词器
      • 作用2: 设置Lucene的打开索引库的方式: setOpenMode();
 /**
  * APPEND: 表示追加, 如果索引库存在, 就会向索引库中追加数据, 如果索引库不存在, 直接报错
  * CREATE: 表示创建, 不管索引库有没有, 每一次都是重新创建一个新的索引库
  * CREATE_OR_APPEND: 如果索引库有, 就会追加, 如果没有 就会创建索引库,默认值
  */
 config.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);

3.Document: 文档

在Lucene中, 每一条数据以文档的形式进行存储, 文档中也有其对应的属性和值, Lucene中一个文档类似数据库的一个表, 表中的字段类似于文档中的字段,只不过这个文档只能保存一条数据,Document看做是一个文件, 文件的属性就是文档的属性, 文件对应属性的值就是文档的属性的值 content.

一个文档中可以有多个字段, 每一个字段就是一个field对象,不同的文档可以有不同的属性,字段也有其对应数据类型, 故Field类也提供了各种数据类型的实现类

4 分词器

Analyzer: 分词器,用于对文档中的数据进行分词, 其分词的效果取决于分词器的选择, Lucene中根据各个国家制定了各种语言的分词器,对中文有一个ChineseAnalyzer 但是其分词的效果, 是将中文进行一个一个字的分开,针对中文分词一般只能使用第三方的分词词:一般采用IK分词器

4.1集成ik分词器
<dependency>
    <groupId>com.janeluo</groupId>
    <artifactId>ikanalyzer</artifactId>
    <version>2012_u6</version>
</dependency>

3.lucene的查询操作

3.1 基础查询

        public void test() throws IOException, ParseException {
            DirectoryReader reader = DirectoryReader.open(FSDirectory.open(new File("H:\\xx")));
            IndexSearcher indexSearcher  = new IndexSearcher(reader);
    
            QueryParser queryParser = new QueryParser("content",new IKAnalyzer());
            Query query = queryParser.parse("程序员");

            TopDocs topDocs = indexSearcher.search(query, Integer.MAX_VALUE);
    
            ScoreDoc[] scoreDocs =  topDocs.scoreDocs;
            int len = topDocs.totalHits;
    
            for (ScoreDoc scoreDoc : scoreDocs) {
                int docId = scoreDoc.doc;//获取文档的id
                float score = scoreDoc.score;//当前这个文档的得分数
                // 根据给定的id  查询对应的文档内容
                Document document = indexSearcher.doc(docId);
    
                String id = document.get("id");
                String content = document.get("content");
            }
        }

3.2 lucene查询的api详解

  • IndexSearcher: Lucene中查询对象, 用来执行查询和排序操作
    • 常用方法:
      • search(Query query, int n);//执行查询
        • 参数1: 查询条件
        • 参数2: 返回的最大条数
      • search(Query query, int n,Sort sort);
        • 参数1: 查询的条件
        • 参数2: 返回的最大的条数
        • 参数3: 排序
      • doc(int id);//根据文档id查询文档对象
  • IndexReader: 索引库读取工具
    • 使用DirectoryReader来打开索引库
  • Query:查询对象
    • 获取方式:
      • 通过查询解析器
        • 单字段的解析器: queryParse
        • 多字段的解析器: multiFieldQueryParse
      • 使用Lucene自定义的实现类
        • Lucene中提供了五种常用的多样化的查询
  • TopDocs:查询结果对象
    • 第一部分: 查询到的总条数
      • int topDocs.totalHits
    • 第二部分: 得分文档的数组
      • ScoreDoc[] topDocs.scoreDocs;
  • ScoreDoc: 得分文档对象
    • 第一部分: 文档的id
      • topDoc.doc
    • 第二部分: 文档的得分
      • topDoc.score

3.3 抽取一个公共查询接口


    public void queryToLucene(Query query) throws IOException {
        IndexSearcher indexSearcher = new IndexSearcher(DirectoryReader.open(FSDirectory.open(new File("H:\\xx"))));
        TopDocs topDocs = indexSearcher.search(query, Integer.MAX_VALUE);

        ScoreDoc[] scoreDocs =  topDocs.scoreDocs;
        int len = topDocs.totalHits;

        for (ScoreDoc scoreDoc : scoreDocs) {
            int docId = scoreDoc.doc;//获取文档的id
            float score = scoreDoc.score;//当前这个文档的得分数
            Document document = indexSearcher.doc(docId);
            String id = document.get("id");
            String content = document.get("content");
            String title = document.get("title");
        }
    }

3.3 词条查询 TermQuery

        public void test() throws IOException {
            TermQuery termQuery = new TermQuery(new Term("content","天气"));
            queryToLucene(termQuery);
        }

3.4 通配符查询 WildcardQuery

        //    WildcardQuery: 通配符查询
        // ?: 占位符, 表示占用一个字符,必须缺少一个
        // *: 占位符, 表示占用多个字符(0到多个)
        //如果只显示一个*, 表示查询全部数据
        public void wildcardQueryToLucene() throws IOException {
            WildcardQuery wildcardQuery = new WildcardQuery(new Term("content","*"));
            queryToLucene(wildcardQuery);
        }

3.5 模糊查询 FuzzyQuery

        //模糊查询:fuzzQuery
        // 模糊查询指定的用户的输入的内容进行 替换, 补位, 移动  
        public void fuzzQueryToLucene() throws IOException {
            FuzzyQuery fuzzyQuery = new FuzzyQuery(new Term("content","气天"),2);
            queryToLucene(fuzzyQuery);
        }

3.6 组合查询 BooleanQuery

        //组合查询
        //BooleanQuery:本身没有任何的条件
        //MUST: 此条件必须包含
        //MUST_NOT: 不能含有此条件里面的内容
        //SHOULD: 指的可选的, 如果有就返回, 如果没有就不管, 查询和其他条件的并集
        public void booleanQueryToLucene() throws IOException {
            BooleanQuery booleanQuery = new BooleanQuery();
            FuzzyQuery fuzzyQuery = new FuzzyQuery(new Term("content","lucene"),2);
    
            booleanQuery.add(fuzzyQuery, BooleanClause.Occur.MUST);
            NumericRangeQuery numericRangeQuery = NumericRangeQuery.newLongRange("id",10L,20L,false,true);
            booleanQuery.add(numericRangeQuery, BooleanClause.Occur.MUST);
            
            queryToLucene(booleanQuery);
        }

3.7 lucene中删除修改

        public void delIndexToLucene() throws IOException, ParseException {

            IndexWriter indexWriter = new IndexWriter(FSDirectory.open(new File("H:\\test")),new IndexWriterConfig(Version.LATEST,new IKAnalyzer()));
    
            // indexWriter.deleteAll();//全部删除
            // indexWriter.deleteDocuments(new Term("",""));//根据对应的词条进行删除
    
            QueryParser queryParser = new QueryParser("content",new IKAnalyzer());
            Query query = queryParser.parse("天气");
            indexWriter.deleteDocuments(query); 
    
            indexWriter.commit();

            indexWriter.close();
        }

3.8 Lucene的分页

        // lucene本质上不支持分页
        public void limitToLucene() throws IOException {
            int page = 2 ;  //当前页
            int pageSize = 5; //每页显示的条数
    
            IndexSearcher indexSearcher = new IndexSearcher(DirectoryReader.open(FSDirectory.open(new File("H:\\xx"))));
    
            TermQuery termQuery = new TermQuery(new Term("content","xx"));
            TopDocs topDocs = indexSearcher.search(termQuery, page*pageSize);
    
            ScoreDoc[] scoreDocs =  topDocs.scoreDocs;//返回当前文档集合
            int len = topDocs.totalHits;// 返回的数量

            //起始的条数 : limit ? ,?
            for (int i = (page-1)*pageSize; i<page*pageSize ; i++) {
                int docId = scoreDocs[i].doc;
                float score = scoreDocs[i].score;

                Document document = indexSearcher.doc(docId);
                String id = document.get("id");
                String content = document.get("content");
                String title = document.get("title");
            }
        }
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值