• Spring Data ElasticSearch 及Kibana调用Restful


    什么是spring Data

    Spring Data是一个用于简化数据库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快
    捷,并支持map-reduce框架和云计算数据服务。 Spring Data可以极大的简化JPA的写法,可以在几乎不用写实现
    的情况下,实现对数据的访问和操作。除了CRUD外,还包括如分页、排序等一些常用的功能。
    Spring Data的官网:http://projects.spring.io/spring-data/

    Spring Data常用的功能模块如下:

    spring data commons
    spring data JPA
    spring data Redis
    spring data for Apache Solr
    spring data ElasticSearch

    什么是Spring Data ElasticSearch 

    Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操作,将原始操作elasticSearch的客户端API 进
    行封装 。Spring Data为Elasticsearch项目提供集成搜索引擎。Spring Data Elasticsearch POJO的关键功能区域为
    中心的模型与Elastichsearch交互文档和轻松地编写一个存储库数据访问层。
    官方网站:http://projects.spring.io/spring-data-elasticsearch/

    Spring Data ElasticSearch 使用

    spring boot实现

    引入坐标

    <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.1.RELEASE</version>
        </parent>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
            </dependency>
        </dependencies>

    添加application.properties

    # ES
    #开启 Elasticsearch 仓库(默认值:true)
    spring.data.elasticsearch.repositories.enabled=true
    #默认 9300 是 Java 客户端的端口。9200 是支持 Restful HTTP 的接口
    spring.data.elasticsearch.cluster-nodes = 127.0.0.1:9300
    #spring.data.elasticsearch.cluster-name Elasticsearch 集群名(默认值: elasticsearch)
    #spring.data.elasticsearch.cluster-nodes 集群节点地址列表,用逗号分隔。如果没有指定,就启动一个客户端节点
    #spring.data.elasticsearch.propertie 用来配置客户端的额外属性
    #连接超时的时间
    spring.data.elasticsearch.properties.transport.tcp.connect_timeout=120s

    创建SpringBoot运行器类

    创建实体类

    /**
     其中,注解解释如下:
     @Document(indexName="blob3",type="article"):
     indexName:索引的名称(必填项)
     type:索引的类型
    
     @Id:主键的唯一标识
     @Field(index=true,analyzer="ik_smart",store=true,searchAnalyzer="ik_smart",type =
     FieldType.text)
     index:是否索引
     analyzer:存储时使用的分词器
     searchAnalyze:搜索时使用的分词器
     store:是否存储
     type: 数据类型
    
     注: 一旦添加了@Filed注解,所有的默认值都不再生效。此外,如果添加了@Filed注解,那么type字段必须指定。
     所以一般不用添加。
     */
    @Document(indexName = "blog3",type = "article")
    public class Article {
    
        //@Field(store = true,type = FieldType.Integer)
        private Integer id;
        @Field(index = true,store = true,analyzer = "ik_smart",searchAnalyzer = "ik_smart",type = FieldType.text)
        private String title;
        @Field(index = true,store = true,analyzer = "ik_smart",searchAnalyzer = "ik_smart",type = FieldType.text)
        private String content;

    增删改查

    test

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = ApplicationRun.class)
    public class TestSpringDataES {
    
        @Autowired
        private ArticleService as;
    
        @Test
        //保存
        public void testSave(){
            Article a = new Article();
            a.setId(1);
            a.setTitle("elasticSearch 3.0版本发布...更新");
            a.setContent("ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口");
    
            as.save(a);
        }
        @Test//修改
        public void testUpdate(){
            Article a = new Article();
            a.setId(1);
            a.setTitle("elasticSearch 3.01版本发布...更新");
            a.setContent("ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口");
    
            as.save(a);
        }
    
        @Test
        //删除
        public void testDelete(){
            Article a = new Article();
            a.setId(1);
    
            as.delete(a);
        }
        @Test
        //批量保存
        public void testSave2(){
            for (int i = 1; i <= 100; i++) {
                Article a = new Article();
                a.setId(i);
                a.setTitle(i+"elasticSearch 3.0版本发布...更新");
                a.setContent(i+"ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口");
    
                as.save(a);
            }
        }
        @Test
        //查询所有保存
        public void testFindAll(){
    
            Iterable<Article> list = as.findAll();
            for (Article article : list) {
                System.out.println(article);
            }
        }
        @Test
        public void TestFindByPage(){
           // Pageable pageable= PageRequest.of(1,10);
           Pageable pageable= PageRequest.of(1,10, Sort.by(Sort.Order.asc("id;")));
            Page page = as.findByPage(pageable);
            List<Article> list = page.getContent();
            for (Article article : list) {
                System.out.println(article);
            }
        }
        @Test
        //根据title查询
        public void testFindByTitle(){
            List<Article> list = as.findByTitle("版本");
            for (Article article : list) {
                System.out.println(article);
            }
        }
    
        @Test
        //根据title查询
        public void testFindByTitlePage(){
            Pageable pageable=PageRequest.of(0,20,Sort.by(Sort.Order.asc("id")));
            Page page = as.findByTitle("版本", pageable);
            List<Article> list = page.getContent();
            for (Article article : list) {
                System.out.println(article);
            }
        }
    }

    service

    public interface ArticleService {
        //保存
        public void save(Article article);
        //删除
        public void delete(Article article);
    
        //查询
        public Iterable<Article> findAll();
    
        //分页查询
        public Page findByPage(Pageable pageable);
    
        public List<Article> findByTitle(String title);
        public Page findByTitle(String title,Pageable pageable);
    }

    impl

    @Service
    public class ArticleServiceImpl implements ArticleService {
    
        @Autowired
        private ArticleDao articleDao;
        @Override
        public void save(Article article) {
            articleDao.save(article);
        }
    
        @Override
        public void delete(Article article) {
            articleDao.delete(article);
        }
    
        @Override//Sort.by(Sort.Order.asc("id")  根据id排序
        public Iterable<Article> findAll() {
            return articleDao.findAll(Sort.by(Sort.Order.asc("id")));
        }
    
        @Override
        public Page findByPage(Pageable pageable) {
            return articleDao.findAll(pageable);
        }
    
        @Override
        public List<Article> findByTitle(String title) {
            return articleDao.findByTitle(title);
        }
    
        @Override
        public Page findByTitle(String title, Pageable pageable) {
            return articleDao.findByTitle(title,pageable);
        }
    
    }

    dao

    //ElasticsearchRepository<实体类,实体类的主键类型> : 提供了CRUD的操作
    public interface ArticleDao extends ElasticsearchRepository<Article,Integer> {
    
        //根据title字段查询
        public List<Article> findByTitle(String title);
    
        public Page findByTitle(String title, Pageable pageable);
    }

    常用查询命名规则

    kibana调用RestAPI

    什么是kibana

    Kibana是一个基于Node.js的Elasticsearch索引库数据统计工具,可以利用Elasticsearch的聚合功能,生成各种图表,如柱形图,线状图,饼图等。
    而且还提供了操作Elasticsearch索引数据的控制台,并且提供了一定的API提示,非常有利于我们学习Elasticsearch的语法。

    安装

    因为Kibana依赖于node,需要在windows下先安装Node.js,然后安装kibana,最新版本与elasticsearch保持一致,也是5.6.8
    
    解压即可!

    运行

    进入安装目录下的bin目录-->双击kibana.bat

    发现kibana的监听端口是5601

    我们访问:http://127.0.0.1:5601

    控制台

    进入之后选择左侧的DevTools菜单,即可进入控制台页面,在页面右侧,我们就可以输入请求,访问Elasticsearch了。

    创建索引库

    语法

    Elasticsearch采用Rest风格API,因此其API就是一次http请求,你可以用任何工具发起http请求
    
    创建索引的请求格式:
    - 请求方式:PUT
    - 请求路径:/索引库名

    使用kibana创建

    相当于是省去了elasticsearch的服务器地址

    而且还有语法提示,非常舒服。

    查看索引数据库

    语法

    GET /索引库名

     删除索引库

    语法

    DELETE /索引库名

    类型及映射操作

    有了`索引库`,等于有了数据库中的`database`。接下来就需要索引库中的`类型`了,也就是数据库中的`表`。创建数据库表需要设置字段约束,索引库也一样,
    在创建索引库的类型时,需要知道这个类型下有哪些字段,每个字段有哪些**约束**信息,这就叫做`字段映射(mapping)` 字段的约束我们在学习Lucene中我们都见到过,包括到不限于: - 字段的数据类型 - 是否要存储 - 是否要索引 - 是否分词 - 分词器是什么

    创建字段映射

    语法

    PUT /索引库名/_mapping/类型名称
    {
      "properties": {
        "字段名": {
          "type": "类型",
          "index": true"store": true"analyzer": "分词器"
        }
      }
    }
    • 类型名称:就是前面将的type的概念,类似于数据库中的表 字段名:任意填写,下面指定许多属性,例如:

    • type:类型,可以是text、long、short、date、integer、object等

    • index:是否索引,默认为true

    • store:是否存储,默认为false

    • analyzer:分词器,这里的ik_max_word即使用ik分词器

    查看映射关系

    语法

    GET /索引库名/_mapping

    附录:映射属性

    1)type

    Elasticsearch中支持的数据类型非常丰富:

    这里说几个关键的:

    • String类型,又分两种:

      • text:可分词,不可参与聚合

      • keyword:不可分词,数据会作为完整字段进行匹配,可以参与聚合

    • Numerical:数值类型,分两类

      • 基本数据类型:long、interger、short、byte、double、float、half_float

      • 浮点数的高精度类型:scaled_float

        • 需要指定一个精度因子,比如10或100。elasticsearch会把真实值乘以这个因子后存储,取出时再还原。

    • Date:日期类型

      elasticsearch可以对日期格式化为字符串存储,但是建议我们存储为毫秒值,存储为long,节省空间。

    • Array:数组类型

      • 进行匹配时,任意一个元素满足,都认为满足

      • 排序时,如果升序则用数组中的最小值来排序,如果降序则用数组中的最大值来排序

    • Object:对象

    {
      name:"Jack",
      age:21,
      girl:{
    name: "Rose",
          age:21
      }
    }

    如果存储到索引库的是对象类型,例如上面的girl,会把girl编程两个字段:girl.name和girl.age

    2)index

    index影响字段的索引情况。

    • true:字段会被索引,则可以用来进行搜索过滤。默认值就是true

    • false:字段不会被索引,不能用来搜索

    index的默认值就是true,也就是说你不进行任何配置,所有字段都会被索引。

    但是有些字段是我们不希望被索引的,比如商品的图片信息,就需要手动设置index为false。

    3)store

    是否将数据进行额外存储。

    在学习lucene和solr时,我们知道如果一个字段的store设置为false,那么在文档列表中就不会有这个字段的值,用户的搜索结果中不会显示出来。

    但是在Elasticsearch中,即便store设置为false,也可以搜索到结果。

    原因是Elasticsearch在创建文档索引时,会将文档中的原始数据备份,保存到一个叫做_source的属性中。而且我们可以通过过滤_source来选择哪些要显示,哪些不显示。

    而如果设置store为true,就会在_source以外额外存储一份数据,多余,因此一般我们都会将store设置为false,事实上,store的默认值就是false。

    4)boost

    权重,新增数据时,可以指定该数据的权重,权重越高,得分越高,排名越靠前。

    一次创建索引库和类型

    put /索引库名
    {
        "settings":{
            "索引库属性名":"索引库属性值"
        },
        "mappings":{
            "类型名":{
                "properties":{
                    "字段名":{
                        "映射属性名":"映射属性值"
                    }
                }
            }
        }
    }

    文档操作

    新增文档

    通过POST请求,可以向一个已经存在的索引库中添加文档数据。

    POST /索引库名/类型名
    {
        "key":"value"
    }

    另外,需要注意的是,在响应结果中有个_id字段,这个就是这条文档数据的唯一标示,以后的增删改查都依赖这个id作为唯一标示。

    可以看到id的值为:r9c1KGMBIhaxtY5rlRKv,这里我们新增时没有指定id,所以是ES帮我们随机生成的id。

    查看文档

    根据rest风格,新增是post,查询应该是get,不过查询一般都需要条件,这里我们把刚刚生成数据的id带上。

    通过kibana查看数据:

    GET /test1/goods/r9c1KGMBIhaxtY5rlRKv

    新增文档并自定义id

    POST /索引库名/类型/id值
    {
        ...
    }
    示例:
    POST /test1/goods/2
    {
        "title":"大米手机",
        "images":"http://image.leyou.com/12479122.jpg",
        "price":2899.00
    }

    修改数据

    把刚才新增的请求方式改为PUT,就是修改了。不过修改必须指定id,

    • id对应文档存在,则修改

    • id对应文档不存在,则新增

    比如,我们把使用id为3,不存在,则应该是新增:

    PUT /test1/goods/3
    {
        "title":"超米手机",
        "images":"http://image.leyou.com/12479122.jpg",
        "price":3899.00,
        "stock": 100,
        "saleable":true
    }

    我们再次执行刚才的请求,不过把数据改一下:

    PUT /test1/goods/3
    {
        "title":"超大米手机",
        "images":"http://image.leyou.com/12479122.jpg",
        "price":3299.00,
        "stock": 100,
        "saleable":true
    }

    删除数据

    删除使用DELETE请求,同样,需要根据id进行删除:

    语法

    DELETE /索引库名/类型名/id值

    查询

    • 基本查询

    • _source过滤

    • 结果过滤

    • 高级查询

    • 排序

    基本语法

    GET /索引库名/_search
    {
        "query":{
            "查询类型":{
                "查询条件":"查询条件值"
            }
        }
    }

    这里的query代表一个查询对象,里面可以有不同的查询属性

    • 查询类型:

      • 例如:match_all, matchterm , range 等等

    • 查询条件:查询条件会根据类型的不同,写法也有差异

    查询所有(match_all)

    GET /test1/_search
    {
        "query":{
            "match_all": {}
        }
    }
    • query:代表查询对象

    • match_all:代表查询所有

    匹配查询

    我们先加入一条数据

    PUT /test1/goods/3
    {
        "title":"小米电视4A",
        "images":"http://image.leyou.com/12479122.jpg",
        "price":3899.00
    }
    • or关系

    match类型查询,会把查询条件进行分词,然后进行查询,多个词条之间是or的关系

    GET /test1/_search
    {
        "query":{
            "match":{
                "title":"小米电视"
            }
        }
    }
    • and关系

    某些情况下,我们需要更精确查找,我们希望这个关系变成and,可以这样做:

    GET /goods/_search
    {
        "query":{
            "match":{
                "title":{"query":"小米电视","operator":"and"}
            }
        }
    }

    词条匹配

    term 查询被用于精确值 匹配,这些精确值可能是数字、时间、布尔或者那些未分词的字符串

    GET /test1/_search
    {
        "query":{
            "term":{
                "price":2699.00
            }
        }
    }

    模糊查询(fuzzy)

    我们新增一个商品:

    POST /test1/goods/4
    {
        "title":"apple手机",
        "images":"http://image.leyou.com/12479122.jpg",
        "price":6899.00
    }

    fuzzy 查询是 term 查询的模糊等价。它允许用户搜索词条与实际词条的拼写出现偏差,但是偏差的编辑距离不得超过2:

    GET /test1/_search
    {
      "query": {
        "fuzzy": {
          "title": "appla"
        }
      }
    }

    上面的查询,也能查询到apple手机

    我们可以通过fuzziness来指定允许的编辑距离:

    GET /test1/_search
    {
      "query": {
        "fuzzy": {
            "title": {
                "value":"appla",
                "fuzziness":1
            }
        }
      }
    }

    排序

    sort 可以让我们按照不同的字段进行排序,并且通过order指定排序的方式

    GET /test1/_search
    {
    "query": {
    "match": {
    "title": "小米手机"
    }
    },
    "sort": [
    {
    "price": {
    "order": "desc"
    }
    }
    ]
    }

    分页

    elasticsearch的分页与mysql数据库非常相似,都是指定两个值:

    • from:开始位置

    • size:每页大小

    GET /test1/_search
    {
      "query": {
        "match_all": {}
      },
      "sort": [
        {
          "price": {
            "order": "asc"
          }
        }
      ],
      "from": 3,
      "size": 3
    }

    高亮

    高亮原理:

    • 服务端搜索数据,得到搜索结果

    • 把搜索结果中,搜索关键字都加上约定好的标签

    • 前端页面提前写好标签的CSS样式,即可高亮

    elasticsearch中实现高亮的语法比较简单:

    GET /test1/_search
    {
      "query": {
        "match": {
          "title": "手机"
        }
      },
      "highlight": {
        "pre_tags": "<em>",
        "post_tags": "</em>", 
        "fields": {
          "title": {}
        }
      }
    }

    在使用match查询的同时,加上一个highlight属性:

    • pre_tags:前置标签

    • post_tags:后置标签

    • fields:需要高亮的字段

      • title:这里声明title字段需要高亮,后面可以为这个字段设置特有配置,也可以空.

  • 相关阅读:
    hadoop的live node为0
    python其中一个子线程,则退出全部线程,再退出进程
    hbase安装
    hive安装
    手游设备ID
    C++对C的改进(1)
    C++析构函数
    C++构造函数
    Linux0.11内核剖析--内核代码(kernel)--sched.c
    MIME简介
  • 原文地址:https://www.cnblogs.com/WonderfulU/p/11209654.html
Copyright © 2020-2023  润新知