zoukankan      html  css  js  c++  java
  • ElasticSearch

    @

    ElasticSearch概述

    ElasticSearch,简称es,es是一个开源的高拓展分布式全文检索引擎,它可以近乎实时的存储检索数据;本身拓展性很好,它可以拓展到上百台服务器,处理PB级别的数据。es也使用java开发并使用Lucene的复杂性,从而让全文检索变得简单
    据国际权威的数据库产品评测机构DB Engines的统计,2016年1月,ElasticSearch已超过solr等成为排名第一的搜索引擎类应用

    ElasticSearch和solr的差别

    ElasticSearch简介

    ElasticSearch是一个实时分布式搜索和分析引擎,它让你以前所未有的速度处理大数据的可能
    它用于全文搜索,结构化搜索,分析以及这三者混合使用
    ElasticSearch是一个基于Apache Lucene(TM)的开源搜索引擎。无论是在开源还是专有邻域,Lucene可以被认为是迄今为止最先进、性能最好的,功能最全的搜索引擎库。
    但是。Lucene只是一个库。想要使用它,你必须使用java作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene非常复杂,你需要更深入的了解检索的相关知识来理解它是如何工作的。
    ElasticSearch也使用java开发并使用Lucene作为其核心来实现所有索引和功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文检索变得简单

    Solr简介

    Solr是Apache下的顶级开源项目,采用java开发,它是基于Lucene的全文检索服务器。solr提供优化比Lucene跟为丰富的查询语言,同时实现了可配置、可拓展,并对索引、搜索性能进行了优化
    solr可以独立运行,运行在jetty、tomcat等这些servlet容器中,Sole索引的实现方法很简单,用post方法向solr服务器发送一条可描述Filed及其内容的XML文档,Solr根据xml文档的添加、删除、更新索引、Solr搜索只需要发送HTTP GET请求,然后对solr返回xml、json等格式的查询结果进行解析,组织页面布局、solr不提供构建UI的功能,solr提供了一个管理界面,通过管理界面可以对查询的solr的配置和运行情况
    Solr是一个开源搜索平台,用于构建搜索应用程序。
    是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口
    它建立在Lucene(全文搜索引擎)之上。 Solr是企业级的,快速的和高度可扩展的。

    Lucene简介

    Lucene 是一个基于 Java 的全文信息检索工具包,它不是一个完整的搜索应用程序,而是为你的应用程序提供索引和搜索功能的一个开源框架。Lucene 目前是 Apache Jakarta 家族中的一个开源项目。也是目前最为流行的基于 Java 开源全文检索工具包。

    目前已经有很多应用程序的搜索功能是基于 Lucene 的,比如 Eclipse 的帮助系统的搜索功能。Lucene 能够为文本类型的数据建立索引,所以你只要能把你要索引的数据格式转化的文本的,Lucene 就能对你的文档进行索引和搜索。比如你要对一些 HTML 文档,PDF 文档进行索引的话你就首先需要把 HTML 文档和 PDF 文档转化成文本格式的,然后将转化后的内容交给 Lucene 进行索引,然后把创建好的索引文件保存到磁盘或者内存中,最后根据用户输入的查询条件在索引文件上进行查询。不指定要索引的文档的格式也使 Lucene 能够几乎适用于所有的搜索应用程序。

    ElasticSearch与solr比较

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    ElasticSearch vs solr 总结

    1. es基本就是开箱使用,非常简单,Solr安装比较复杂一点
    2. Solr支持更多格式的数据,比如json,xml,csv,而ElasticSearch仅支持json文件格式
    3. Solr利用Zookeeper进行分布式管理,而ElasticSearch自身带有分布式协调管理功能。
    4. Solr官方提供的功能更多,而ElasticSearch本身更注重与核心功能,高级功能多有第三方插件提供,例如图形化页面需要kibana友好支撑
    5. Solr查询快,但更新索引满,用于电商等查询多的应用
    6. ElasticSearch建立索引快(查询慢),实时性查询快,用于facebook新浪等搜索
    7. Solr是传统搜索应用的有力解决方案,但ElasticSearch更适用新兴的实时搜索应用
    8. Solr比较成熟,有一个更大,更成熟的用户、开发和贡献者社区,而ElasticSearch相对开发维护者较少,更新太快,学习使用成本较高

    ElasticSearch安装

    声明:JDK1.8,最低要求,ElasticSearch客户端,界面工具
    java开发,ElasticSearch的版本和我们之后对应的java的核心jar包!版本对应,JDK环境是正常

    下载 https://www.elastic.co/cn/
    在这里插入图片描述
    在这里插入图片描述
    华为云的镜像去下载
    ElasticSearch: https://mirrors.huaweicloud.com/elasticsearch/?C=N&O=D
    logstash: https://mirrors.huaweicloud.com/logstash/?C=N&O=D
    kibana: https://mirrors.huaweicloud.com/kibana/?C=N&O=D

    链接: https://pan.baidu.com/s/1xhpIqT8Tm-jN_h2ir9xlwA 提取码: jv4h

    1. 下载后解压
      在这里插入图片描述
    2. 目录介绍
    bin  启动文件
    config  配置文件
    		log4j2 日志配置文件
    		jvm.options  java虚拟机相关配置
    		elasticsearch.yml  elasticsearch的配置文件  默认9200端口! 跨域!
    lib      相关jar包
    modules  功能目录
    plugins  插件
    
    1. 双击bin/elasticsearch.bat文件
      在这里插入图片描述
    2. 访问http://127.0.0.1:9200
      在这里插入图片描述
      在这里插入图片描述
    3. 安装可视化界面 ElasticSearch head
      下载:https://github.com/mobz/elasticsearch-head
      在这里插入图片描述
      在这里插入图片描述
    4. 报错:跨域问题
      解决:
      打开elasticsearch.yml文件进行配置
      在这里插入图片描述
    http.cors.enabled: true
    http.cors.allow-origin: "*"
    
    1. 重新启动elasticSearch和elasticsearch-head
      在这里插入图片描述
      索引:相当于一个数据库
      在这里插入图片描述
      新建一个索引
      在这里插入图片描述

    安装kibana

    了解ELK

    ELK是elasticSearch、Logstash、kibana三大开源框架首字母大写的简称。市面上也被称为Elastic Stack。其中elasticSearch是一个基于Lucene、分布式、通过RESTful方式进行交互的近实时搜索平台框架。像类似于百度、谷歌这种大数据全文搜索引擎的场景都可以使用elasticSearch作为底层支持框架、可见elasticSearch提供的搜索能力确实强大,elasticSearch也被市面上简称为es。
    Logstash是ELK的中央数据引流引擎,用于从不同目标(文件/数据存储/MQ)收集的不同格式数据,经过过滤后支持输出带不同的目的地(文件/MQ/redis/elasticSearch/kafka)等。kibana可以将elasticSearch的数据通过友好的页面展示出来,提供实时分析的功能
    在这里插入图片描述

    下载地址:https://www.elastic.co/cn/downloads/kibana
    注意:es版本和kibana版本尽量保持一致
    在这里插入图片描述

    下载完解压
    在这里插入图片描述
    启动测试:bin/kibana.bat
    在这里插入图片描述
    端口:5601
    访问:http://localhost:5601
    在这里插入图片描述
    英文看不懂咋办?使用汉化插件

    打开/config/kibana.yml文件 设置i18n.locale: "zh-CN"
    在这里插入图片描述

    重新启动kibana
    在这里插入图片描述

    ES核心概念

    1、索引
    2、字段类型(mapping)
    3、文档(documents)

    概述
    elasticsearch是面向文档,关系型数据库和elasticsearch客观的对比
    集群,节点所以,类型,文档,分片,映射是什么?

    Relational DB elasticsearch
    数据库(database) 索引(indices)
    表(tables) type
    行(rows) documents
    字段(colums) fieds

    elasticsearch(集群)中可以包含多个索引(数据库),每个索引可以包含多个类型(表),每个类型可以包含多个文档(行),每个文档中有保安多个字段(列)。

    物理设计:
    elasticsearch在后台吧每个索引划分成多个分片,每分分片可以在集群中的不同服务器间迁移

    逻辑设计:
    一个索引类型中,包含多个文档,比如说文档1,文档2。当我们索引一篇文档时,可以通过这样的一个顺序找到它:索引>类型>文档id>,通过这个组合我们就能索引带某个具体的文档。注意:ID不必是整数,实际上是一个字符串

    文档

    之前说 elasticsearch是面向文档的,那么就意味着索引和搜索数据的最小单位是文档, elasticsearch中,文档有几个重要属性:

    • 自我包含,一文档同时包含字段和对应的值,也就是同时包含 key: value!name: guangshen
    • 可以是层次型的,一个文档中包含自文档,复杂的逻辑实体就是这么来的
    • 灵活的结构,文档不依赖预先定义的模式,我们知道关系型数据库中,要提前定义字段才能使用,在 elasticsearch中,对于字
      段是非常灵活的,有时候,我们可以忽略该字段,或者动态的添加一个新的字段。

    类型

    类型是文档的逻辑容器,就像关系型数据库一样,表格是行的容器。类型中对于字段的定义称为映射,比如name映射为字符串类型。我们说文档是无模式的,它们不需要拥有映射中所定义的所有字段,比如新增一个字段,那么 elasticsearch是怎么做的呢?
    elasticsearch会自动的将新字段加入映射,但是这个字段的不确定它是什么类型, elasticsearch就开始猜,如果这个值是18,那elasticsearch会认为它是整形。但是 elasticsearch也可能猜不对,所以最安全的方式就是提前定义好所需要的映射,这点跟关系
    型数据库殊途同归了,先定义好字段,然后再使用,别整什么蛾子。

    索引

    就是数据库!
    索引是映射类型的容器, elasticsearch中的索引是一个非常大的文档集合。索引存储了映射类型的字段和其他设置。然后它们被存储到了各个分片上了。我们来研究下分片是如何工作的
    在这里插入图片描述

    物理设计:节点和分片如何工作
    一个集群至少有一个节点,而一个节点就是一个 elasricsearch进程,节点可以有多个索引默认的,如果你创建索引,那么索引将会
    有个5个分片( primary shard,又称主分片)构成的,毎一个主分片会有一个副本( replica shard,又称复制分片)
    在这里插入图片描述
    上图是一个有3个节点的集群,可以看到主分片和对应的复制分片都不会在同一个节点内,这样有利于某个节点挂掉了,数据也不于丢失。
    实际上,一个分片是一个 Lucene索引,一个包含倒排索引的文件目录,倒排素引的结构使得 elasticsearchi在不扫描全部文档的情况下,就能告诉你哪些文档包含特定的关键字。不过,等等,倒排索引是什么鬼?

    倒排索引

    elasticsearch使用的是一种称为倒排索引的结构,采用 lucene倒排索作为底层。这种结构适用于快速的全文搜索,一个索引由文档中所有不重复的列表构成,对于每一个词,都有一个包含它的文档列表。例如,现在有两个文档,每个文档包含如下内容

    Study every day , good good up to forever # 文档1包含的内容
    To forever  , Study every day, good good up  # 文档2包含的内容
    

    为了创建倒排索引,我们首先要将每个文档拆分成独立的词或称为词条或者 tokens),然后创建一个包含所有不重复的词条的排序列表,然后列出每个词条出现在哪个文档

    term doc_1 doc_2
    Study
    To
    ever
    forever
    day
    study
    good
    every
    to
    up

    来看一个示例,比如我们通过博客标签来搜索博客文章。那么倒排索引列表就是这样的一个结构
    在这里插入图片描述
    如果要搜索含有 python标签的文章,那相对于査找所有原始数据而言,查找倒排索引后的数据将会快的多。只需要查看标签这栏,然后获取相关的文章ID即可。完全过滤掉无关的所有数据,提高效率!

    elasticsearche的索引和 Lucene的索引对比

    在 elasticsearcht中,索引这个词被频繁使用,这就是术语的使用。在 elasticsearch中,索引被分为多个分片,每份分片是一个
    Lucene的索引。所以一个 elasticsearch素引是由多个 Lucene索引组成的。别问为什么,谁让 elasticsearch使用 Lucene作为底层呢!
    如无特指,说起索引都是指 elasticsearchi的索引
    接下来的一切操作都在 kibana中 Dev Tools下的 Consale里完成。
    基础操作

    IK分词器插件

    什么是IK分词器

    分词:即把一段中文或者別的划分成一个个的关键字,我们在搜索时候会把自己的信息进行分词,会把数据库中或者索引库中的数据进行分词,然后进行一个匹配操作,默认的中文分词是将每个字看成一个词,比如“我爱jd”会被分为我","爱","j","d”,这显
    然是不符合要求的,所以我们需要安装中文分词器K来解决这个问题。

    如果要使用中文,建议使用ik分词器
    IK提供了两个分词算法: ik smart和 ik max word,其中 ik smart为最少切分, ik max word为最细粒度划分!一会我们测试!

    安装

    下载地址:https://github.com/medcl/elasticsearch-analysis-ik
    下载完毕之后,放入到我们的 elasticsearch插件即可!
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    通过命令查看插件是否加载:elasticsearch-plugin list

    使用kibana测试
    查看不同分词器的效果
    其中 ik smart为最少切分
    在这里插入图片描述

    ik_max_word为细粒度拆分
    在这里插入图片描述
    自定义词典

    1. 在IK分词器config目录下新建一个*.dic文件
      在这里插入图片描述
      编写自己的词汇
      在这里插入图片描述
      配置到IKAnalyzer.cfg.xml中
      在这里插入图片描述
      重新启动es、kibana
      在这里插入图片描述

    Rest风格说明

    一种软件架构风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更筒洁,更有层次,更易于实现缓存等机制。

    基本Rest命令说明

    method url地址 描述
    PUT localhost:9200/索引名称/类型名称/文档id 创建文档(指定文档d)
    POST localhost:9200/索引名称/类型名称 创建文档(随机文档id)
    POST locahost:9200/索引名称/类型名称/文档id/_ update 修改文档
    DELETE localhost::9200/索引名称/类型名称/文档id 删除文档
    GET localhost:9200/索引名称/类型名称文档id 查询文档通过文档d
    POST localhost::9200/索引名称/类型名称/_search 查询所有数据

    索引的基本操作

    运行es,kibana、es-head

    创建一个索引

    PUT /索引名/~类型名~/文档id
    {
    	请求体
    }
    

    在这里插入图片描述
    完成了自动増加了索引!数据也成功的添加了
    在这里插入图片描述
    那么name这个字段用不用指定类型呢。毕亮我们关系型数据库是需要指定类型的啊
    默认类型:

    • 字符串类型:text、keyword
    • 数值类型:ling,integer,short,byte,double,float,half float,scaled float
    • 日期类型:date
    • te布尔值类型:boolean
    • 二进制类型:binary
    • 等等

    指定字段的类型
    在这里插入图片描述

    PUT /test2
    {
      "mappings": {
        "properties": {
         "name":{
           "type": "text"
         },
         "age":{
           "type": "long"
         },
         "birthday":{
           "type": "date"
         }
        }
      }
    }
    

    获取索引信息

    GET /索引名/~类型名~/文档id
    

    在这里插入图片描述
    如果自己的文档字段没有指定,那么es就会给我们默认配置字段类型

    展:通过命令 elasticsearch索引情況!通过get_cat/可以获得es的当前的很多信息!
    在这里插入图片描述
    在这里插入图片描述

    修改索引状态

    POST /索引名称/类型名称/文档名称/_update

    PUT /test3/_doc/1
    {
      "name":"joker",
      "age":18,
      "sex":"男"
    }
    
    POST /test3/_doc/1/_update
    {
      "doc":{
        "name":"joker_dj"
      }
    }
    

    在这里插入图片描述
    在这里插入图片描述

    删除索引

    通过 DELETE命令实现州除、根据你的请求来判断是删除索引还是删除文档记录!

    DELETE /索引名称/类型名称/文档名称

    在这里插入图片描述
    删除指定文档
    在这里插入图片描述

    DELETE 索引名称/类型名称/文档id
    {
    	方法体
    }
    例:
    DELETE test3/_doc/1
    {
      "name":"joker_dj"
    }
    

    文档的基本操作

    基本操作

    创建索引

    PUT /joker/user/1
    {
      "name":"joker_dj",
      "age":18,
      "desc":"java小萌新",
      "tags":["技术宅","直男"]
    }
    PUT /joker/user/1
    {
      "name":"joker_dj",
      "age":18,
      "desc":"java小萌新",
      "tags":["技术宅","直男"]
    }
    PUT /joker/user/3
    {
      "name":"李四",
      "age":5,
      "desc":"合伙人",
      "tags":["坏人"]
    }
    
    

    获取文档

    GET /索引名称/类型名称/文档id
    在这里插入图片描述

    修改文档

    重新put一边就是修改 (不推荐)
    version就是数据被改动的次数
    在这里插入图片描述
    POST _update,推荐使用这种更新方式
    在这里插入图片描述

    POST /索引名称/类型名称/文档id/_update
    {
      "doc":{
        "fieds":"value"
      }
    }
    
    POST /joker/user/3/_update
    {
      "doc":{
        "name":"张三的哥哥李四"
      }
    }
    

    文档搜索

    简单的搜索

    GET /索引名称/[类型名称]/[文档id]
    

    在这里插入图片描述
    高级搜索 条件查询

    GET /索引名称/[类型名称]/_search?q=fieds:value
    

    在这里插入图片描述

    复杂操作搜索 select(排序,分页,高亮,模糊査询,精准查询!)

    在这里插入图片描述
    根据_score分数进行排序 查看谁最匹配

    在这里插入图片描述

    只要文档中包含value的就会被查出来 前提是被分词器捕获
    GET /索引名称/类型名称/_search
    {
      "query": {
        "match": {
          "fileds": "value"
        } 
      }
    }
    
    GET /joker/user/_search
    {
      "query": {
        "match": {
          "name": "张三"
        } 
      }
    }
    
    

    在这里插入图片描述

    过滤字段

    GET  /索引名称/类型名称/_search
    {
      "query": {
        "match": {
          "fileds": "value"
        }
      },
      "_source": ["fileds","fileds"]
    }
    
    GET /joker/user/_search
    {
      "query": {
        "match": {
          "name": "张三"
        }
      },
      "_source": ["desc","name"]
    }
    
    

    在这里插入图片描述

    排序

    GET  /索引名称/类型名称/_search
    {
      "query": {
        "match": {
          "fileds": "value"
        }
      },
      "_source": ["fileds","fileds"],
      "sort": [
        {
          "fileds": {
            "order": "desc"
          }
        }
      ]
    }
    
    例:
    GET /joker/user/_search
    {
      "query": {
        "match": {
          "name": "张三"
        }
      },
      "_source": ["desc","name","age"],
      "sort": [
        {
          "age": {
            "order": "desc"
          }
        }
      ]
    }
    
    

    在这里插入图片描述

    分页查询

    GET /joker/user/_search
    {
      "query": {
        "match": {
          "name": "张三"
        }
      },
      "from": 0, # 起始值  page
      "size": 20 # 查询大小 pageSize
    }
    
    

    在这里插入图片描述
    数据下标还是从0开始的,和学的所有数据结构是一样的!
    /seach/{current}/{pageSize}

    布尔查询

    多条件查询
    must 相当于 and

    GET /joker/user/_search
    {
      "query": {
        "bool": {
         "must ": [
           {
             "match": {
               "name": "张三"
             }
           },
           {
             "match": {
               "age": 5
             }
           }
         ]
        }
      }
    }
    
    

    在这里插入图片描述
    should相当于 or

    GET /joker/user/_search
    {
      "query": {
        "bool": {
         "should": [
           {
             "match": {
               "name": "张三"
             }
           },
           {
             "match": {
               "age": 5
             }
           }
         ]
        }
      }
    }
    
    

    在这里插入图片描述

    not操作

    GET /joker/user/_search
    {
      "query": {
        "bool": {
         "must_not": [
           {
             "match": {
               "name": "张三"
             }
           },
           {
             "match": {
               "age": 5
             }
           }
         ]
        }
      }
    }
    

    在这里插入图片描述

    过滤器 filter

    GET /joker/user/_search
    {
      "query": {
        "bool": {
         "must_not": [
           {
             "match": {
               "name": "张三"
             }
           }
         ],
         "filter": {
           "range": {
             "age": {
               "gt": 1, 
             }
           }
         }
        }
      }
    }
    
    

    筛选年龄大于1
    在这里插入图片描述

    • gt 大于
    • lt 小于
    • gte 大于等于
    • lte 小于等于

    匹配多个条件

    多个条件之间使用空格隔开
    只满足其中一个即可查出
    通过分值基本判断
    在这里插入图片描述

    精确查询

    term查询是直接通过倒排索引指定的词条进程精确的查找的!
    关于分词:

    • term :直接查询精确的
    • match:会使用分词器解析!(先分析文档,然后在通过分析的文档进行查询!)

    两个类型 text 、 keyword
    keyword不会被分词器解析
    text 会被分词器解析

    多个值匹配的精确查询

    在这里插入图片描述
    在这里插入图片描述

    高亮查询

    GET /joker/user/_search
    {
      "query": {
        "match": {
          "name":"张三"
        }
      },
      "highlight": {
        "fields": {
          "name":{
            
          }
        }
      }
    }
    
    

    在这里插入图片描述
    自定义高亮标签
    在这里插入图片描述

    GET /joker/user/_search
    {
      "query": {
        "match": {
          "name":"张三"
        }
      },
      "highlight": {
        "pre_tags":"<p class='key' style='color:red'>",
        "post_tags":"</p>",
        "fields": {
          "name":{
            
          }
        }
      }
    }
    
    

    集成SpringBoot

    官方文档:

    https://www.elastic.co/guide/index.html
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    查看文档

    在这里插入图片描述

    导入maven pom依赖

    在这里插入图片描述
    1、找到原生的依赖

    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-high-level-client</artifactId>
        <version>7.6.2</version>
    </dependency>
    

    2、初始化
    用完后关闭客户端
    在这里插入图片描述
    3、分析类中的方法

    1. 创建空的父工程
      在这里插入图片描述

    2. 创建SpringBoot子模块
      在这里插入图片描述
      在这里插入图片描述
      勾选相关依赖
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      下载相关依赖
      在这里插入图片描述
      注意版本问题:要和本地es版本一致,否则可能会出现问题
      在这里插入图片描述
      在这里插入图片描述

    3. 新建配置类
      在这里插入图片描述

    @Configuration
    public class ElasticSearchclientConfig {
        
        @Bean
        public RestHighLevelClient restHighLevelClient(){
            RestHighLevelClient client = new RestHighLevelClient(
                    RestClient.builder(
                            new HttpHost("localhost", 9200, "http")));
            return client;
    
        }
    }
    
    1. Api测试

    创建索引

    在这里插入图片描述

    @SpringBootTest
    class ElasticseachApplicationTests {
        @Autowired
        @Qualifier("restHighLevelClient")
        private RestHighLevelClient client;
    
        //索引的创建 Request
        @Test
        void testCerateIndex() throws IOException {
            //1. 创建索引请求
            CreateIndexRequest request = new CreateIndexRequest("joker_index");
            //2. 执行创建请求 indices.create
            CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
            System.out.println(createIndexResponse);
        }
    }
    
    

    判断索引是否存在

    在这里插入图片描述

        @Test
        void testGetindex() throws IOException {
            GetIndexRequest request = new GetIndexRequest("joker_index");
            boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
            System.out.println(exists);
        }
    

    删除索引

    在这里插入图片描述

    //删除索引
        @Test
        void testDeleteindex() throws IOException {
            DeleteIndexRequest request = new DeleteIndexRequest("test2");
            AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
            System.out.println(delete.isAcknowledged());
        }
    

    创建添加文档

    添加fastjson依赖
    方便json转换
    在这里插入图片描述

    <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.73</version>
            </dependency>
    

    在这里插入图片描述

     //添加文档
        @Test
        void testAddDocument() throws IOException {
            User user = new User("joker_dj", 18);
            //创建请求
            IndexRequest request = new IndexRequest("joker_index");
            // 规则 put joker_index/_doc/1
            request.id("1");
            request.timeout(TimeValue.timeValueSeconds(1));
            request.timeout("1s");
            //将我们的数据放入请求 json
            request.source(JSON.toJSONString(user), XContentType.JSON);
            //客户端发送请求
            IndexResponse indexRespons = client.index(request, RequestOptions.DEFAULT);
            System.out.println(indexRespons.toString());
            System.out.println(indexRespons.status());
        }
    

    获取文档 判断文档是否存在

    在这里插入图片描述

     //获取文档 判断文档是否存在
        @Test
        void testexitdocument() throws IOException {
            GetRequest request = new GetRequest("joker_index", "1");
            //不获取返回的上下文  _source
            request.fetchSourceContext(new FetchSourceContext(false));
            request.storedFields("_none_");
            boolean exists = client.exists(request, RequestOptions.DEFAULT);
            System.out.println(exists);
        }
    

    获取文档的内容

    在这里插入图片描述

    //获取文档的内容
        @Test
        void testGetDocument() throws IOException {
            GetRequest request = new GetRequest("joker_index", "1");
            GetResponse documentFields = client.get(request, RequestOptions.DEFAULT);
            System.out.println(documentFields.toString());//打印文档的内容
        }
    

    更新文档内容

    在这里插入图片描述

    //更新文档信息
        @Test
        void testUpdateDocument() throws IOException {
            UpdateRequest request = new UpdateRequest("joker_index", "1");
            request.timeout("1s");
            User user = new User("joker_djs", 20);
            request.doc(JSON.toJSONString(user),XContentType.JSON);
            UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
            System.out.println(update.status());
        }
    

    删除文档记录

    在这里插入图片描述

     //删除文档记录
        @Test
        void testDeleteRequst() throws IOException {
            DeleteRequest request = new DeleteRequest("joker_index", "1");
            request.timeout("1s");
            DeleteResponse delete = client.delete(request, RequestOptions.DEFAULT);
            System.out.println(delete.status());
        }
    

    批量插入数据

    在这里插入图片描述

     // 批量插入数据
        @Test
        void testBulkRequest() throws IOException {
            BulkRequest bulkRequest = new BulkRequest();
            bulkRequest.timeout("10s");
            ArrayList<User> userList=new ArrayList<>();
            userList.add(new User("joker1",18));
            userList.add(new User("joker2",18));
            userList.add(new User("joker3",18));
            userList.add(new User("joker4",18));
            userList.add(new User("joker5",18));
            userList.add(new User("joker6",18));
            userList.add(new User("joker7",18));
            userList.add(new User("joker8",18));
            for (int i = 0; i < userList.size(); i++) {
                bulkRequest.add(new IndexRequest("joker_index")
                        .id(""+(i+1))
                        .source(JSON.toJSONString(userList.get(i)),XContentType.JSON));
            }
            BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
            System.out.println(bulk.hasFailures()); //false 成功
        }
    

    在这里插入图片描述

    高级查询

    在这里插入图片描述

    //查询
        //搜索请求 SearchRequest
        //条件构造 SearchSourceBuilder
        //MatchAllQueryBuilder
        //TermQueryBuilder 精确查询
        // xxx QueryBuilder 
        @Test
        void testSearch() throws IOException {
            SearchRequest searchRequest = new SearchRequest("joker_index");
            //构建搜索条件
            SearchSourceBuilder SourceBuilder = new SearchSourceBuilder();
            //高亮
            SourceBuilder.highlighter();
            //查询条件 我们可以使用QueryBuidler
            MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
            TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "joker1");
    //        MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
            SourceBuilder.query(matchAllQueryBuilder);
            SourceBuilder.timeout(new TimeValue(60,TimeUnit.SECONDS));
    
            //构建搜索
            searchRequest.source(SourceBuilder);
            /*客户端执行*/
            SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
            System.out.println(JSON.toJSONString(search.getHits()));
            System.out.println("==============================");
            for (SearchHit hit : search.getHits().getHits()) {
                System.out.println(hit.getSourceAsMap());
            }
        }
    

    实战

    项目搭建

    1. 新建一个SpringBoot项目
      在这里插入图片描述
      勾选依赖
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      引入fastjson
     <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.73</version>
            </dependency>
    

    配置文件
    在这里插入图片描述
    引入静态页面
    在这里插入图片描述
    启动访问
    在这里插入图片描述

    爬虫

    数据问题?数据库获取,消息队列中获取中,都可以成为数据源,爬虫!

    爬取数据:(获取请求返回的页面信息,筛选出我们想要的数据就可以了!)

    jsoup

    在这里插入图片描述

    <!--解析网页jsoup-->
            <dependency>
                <groupId>org.jsoup</groupId>
                <artifactId>jsoup</artifactId>
                <version>1.10.2</version>
            </dependency>
    

    编写解析网页工具包

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    把爬取到的数据封装成对象

    在这里插入图片描述

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @ToString
    public class Content {
        private String title;
        private String img;
        private String price;
    }
    
    

    封装工具类

    在这里插入图片描述

    public class HtmlParseUtil {
        public static void main(String[] args) throws IOException {
            new HtmlParseUtil().ParseJD(encode).forEach(System.out::println);
        }
    
        public  List<Content> ParseJD(String keywords) throws IOException {
            //获取请求 :https://search.jd.com/Search?keyword=java
            //需要联网
            String encode = URLEncoder.encode(keywords, "UTF-8");//url字符转义
            String url="https://search.jd.com/Search?keyword="+ keywords;
            //解析网页 (Jsoup返回的Document对象就是JS的Document对象)
            Document document = Jsoup.parse(new URL(url), 30000);
            //所有js的方法都可以使用
            Element element = document.getElementById("J_goodsList");
            //获取所有的li标签
            Elements elements = element.getElementsByTag("li");
    
            ArrayList<Content> goods = new ArrayList<>();
            for (Element el : elements) {
                //关于图片特别多的网站 所有图片都是懒加载
                String img = el.getElementsByTag("img").eq(0).attr("src");//图片
                String price = el.getElementsByClass("p-price").eq(0).text();//价格
                String title = el.getElementsByClass("p-name").eq(0).text();//标题
    
                Content content = new Content(title, img, price);
                goods.add(content);
    
            }
            return goods;
        }
    }
    

    编写elasticsearch配置类

    ElasticSearchclientConfig

    @Configuration
    public class ElasticSearchclientConfig {
    
        @Bean
        public RestHighLevelClient restHighLevelClient(){
            RestHighLevelClient client = new RestHighLevelClient(
                    RestClient.builder(
                            new HttpHost("localhost", 9200, "http")));
            return client;
    
        }
    }
    

    创建index索引

    在这里插入图片描述

    创建业务层

    在这里插入图片描述

    //业务编写
    @Service
    public class ContentService {
        @Autowired
        private RestHighLevelClient restHighLevelClient;
        
        //解析数据放入es中
        public boolean parseContent(String keywords) throws IOException {
            List<Content> contents = new HtmlParseUtil().ParseJD(keywords);
            //把查询得到的数据放到es中
            BulkRequest bulkRequest = new BulkRequest();
            bulkRequest.timeout("2m");
            for (int i = 0; i < contents.size(); i++) {
                bulkRequest.add(new IndexRequest("jd_goods")
                        .source(JSON.toJSONString(contents.get(i)), XContentType.JSON));
                        
            }
            BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
            return !bulk.hasFailures();
        }
    }
    
    

    编写controller

    在这里插入图片描述

    @RestController
    public class ContentController {
        @Autowired
        ContentService service;
        @GetMapping("/parse/{keywords}")
        public boolean parse(@PathVariable("keywords") String keywords) throws IOException {
           return service.parseContent(keywords);
        }
    }
    
    

    运行:localhost:9090/parse/java
    在这里插入图片描述

    获取数据实现搜索功能

    Service层

     //2. 获取数据实现搜索功能
        public List<Map<String,Object>> searchPage(String keywords,int page,int pageSize) throws IOException {
            if(page<=1){
                page=1;
            }
            //条件搜索
            SearchRequest searchRequest = new SearchRequest("jd_goods");
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            //分页
            sourceBuilder.from(page);
            sourceBuilder.size(pageSize);
    	 //模糊匹配
            MatchPhraseQueryBuilder title = QueryBuilders.matchPhraseQuery("title", keywords);
            //精确匹配
           // TermQueryBuilder title = QueryBuilders.termQuery("title", keywords);
            sourceBuilder.query(title);
            sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
            //执行搜索
            searchRequest.source(sourceBuilder);
            SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    
            //解析结果
            ArrayList<Map<String,Object>> list = new ArrayList<>();
            for (SearchHit hit : search.getHits().getHits()) {
                list.add(hit.getSourceAsMap());
            }
            return list;
        }
    

    Controller
    在这里插入图片描述

       @GetMapping("/search/{keywords}/{page}/{pageSize}")
        public List<Map<String,Object>> search(@PathVariable("keywords") String keywords,@PathVariable("page") int page,@PathVariable("pageSize") int pageSize) throws IOException {
            return  service.searchPage(keywords, page, pageSize);
        }
    

    访问测试
    在这里插入图片描述

    前端渲染数据 vue

    下载vue
    npm install vue
    npm install axios
    在这里插入图片描述
    引入工程中
    在这里插入图片描述
    在这里插入图片描述
    编写vue代码
    在这里插入图片描述

    <script>
    new Vue({
        el:"#app",
        data:{
            keywords:"",//搜索的关键字
            result:[]//搜索的结果
        },
        methods:{
            searchkey(){
                var keyword=this.keywords;
               axios.get("/search/"+keyword+"/1/10").then(res=>{
                   this.result=res.data;
               }).catch(err=>{
    
               })
            }
        }
    })
    </script>
    

    数据渲染
    在这里插入图片描述
    在这里插入图片描述

    实现搜索高亮

    在这里插入图片描述
    在这里插入图片描述

    //3. 获取数据实现高亮搜索功能
        public List<Map<String,Object>> searchHighlightPage(String keywords,int page,int pageSize) throws IOException {
            if(page<=1){
                page=1;
            }
            //条件搜索
            SearchRequest searchRequest = new SearchRequest("jd_goods");
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            //高亮
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            highlightBuilder.requireFieldMatch(false);//是否多个字段高亮;
            highlightBuilder.field("title");//设置高亮的字段
            highlightBuilder.preTags("<span style='color:red'>");//设置前缀
            highlightBuilder.postTags("</span>");//设置后缀
            sourceBuilder.highlighter(highlightBuilder);
            //分页
            sourceBuilder.from(page);
            sourceBuilder.size(pageSize);
    
            //模糊匹配
            MatchPhraseQueryBuilder titles = QueryBuilders.matchPhraseQuery("title", keywords);
            //精确匹配
            //TermQueryBuilder title = QueryBuilders.termQuery("title", keywords);
            sourceBuilder.query(titles);
            sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
            //执行搜索
            searchRequest.source(sourceBuilder);
            SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    
            //解析结果
            ArrayList<Map<String,Object>> list = new ArrayList<>();
            for (SearchHit hit : search.getHits().getHits()) {
    
                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                HighlightField title = highlightFields.get("title");
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果
                //解析高亮的字段
                if(title!=null){
                    Text[] fragments = title.fragments();
                    String n_title="";
                    for (Text text : fragments) {
                        n_title+=text;
                    }
                    sourceAsMap.put("title",n_title);
                }
                list.add(sourceAsMap);
            }
            return list;
        }
    

    contrller引用
    在这里插入图片描述
    访问测试
    在这里插入图片描述
    推荐视频 elasticsearch up主 遇见狂神说:
    bilibili链接

  • 相关阅读:
    几种回文算法的比较
    算法与数据结构(五)树表的查找
    算法与数据结构(四)利用哈夫曼树编码解码
    算法与数据结构(三)线性表的查找算法
    主存和cache的地址映射
    算法与数据结构(二)三元组矩阵行列式的计算(用递归)
    算法与数据结构(一)将一个数组中的各节点按照层次遍历插入构成完全二叉树
    服务器被攻击,我真是个人才。
    想学嘛,不想学? 自学是门手艺
    想学嘛,技术人, 请不要封闭自己
  • 原文地址:https://www.cnblogs.com/joker-dj/p/13490202.html
Copyright © 2011-2022 走看看