当前位置:   article > 正文

ElasticSearch全文详解及具体配置_es9300端口修改

es9300端口修改

一、全文检索基础

1.什么是全文检索

将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引

例如:字典。字典的拼音表和部首检字表就相当于字典的索引,对每一个字的解释是非结构化的,如果字典没有音节表和部首检字表,在茫茫辞海中找一个字只能顺序扫描。然而字的某些信息可以提取出来进行结构化处理,比如读音,就比较结构化,分声母和韵母,分别只有几种可以一一列举,于是将读音拿出来按一定的顺序排列,每一项读音都指向此字的详细解释的页数。我们搜索时按结构化的拼音搜到读音,然后按其指向的页数,便可找到我们的非结构化数据——也即对字的解释

这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)

虽然创建索引的过程也是非常耗时的,但是索引一旦创建就可以多次使用,全文检索主要处理的是查询,所以耗时间创建索引是值得的。

2.相关概念

  1. 索引库
    索引库就是存储索引的保存在磁盘上的一系列的文件。里面存储了建立好的索引信息以及文档对象

在这里插入图片描述

一个索引库相当于数据库中的一张表

  1. document对象

    获取原始内容的目的是为了索引,在索引前需要将原始内容创建成文档(Document),文档中包括一个一个的域(Field),域中存储内容。每个文档都有一个唯一的编号,就是文档id

    document对象相当于表中的一条记录

  2. field对象

    如果我们把document看做是数据库中一条记录的话,field相当于是记录中的字段。field是索引库中存储数据的最小单位。field的数据类型大致可以分为数值类型和文本类型,一般需要查询的字段都是文本
    类型的,field的还有如下属性:

    • 是否分词:是否对域的内容进行分词处理。前提是我们要对域的内容进行查询

    • 是否索引:将Field分析后的词或整个Field值进行索引,只有索引方可搜索到

      比如:商品名称、商品简介分析后进行索引,订单号、身份证号不用分词但也要索引,这些将来都
      要作为查询条件

    • 是否存储:将Field值存储在文档中,存储在文档中的Field才可以从Document中获取 比如:商品
      名称、订单号,凡是将来要从Document中获取的Field都要存储

    • term对象 从文档对象中拆分出来的每个单词叫做一个Term,不同的域中拆分出来的相同的单词是不同的term。term中包含两部分一部分是文档的域名,另一部分是单词的内容。term是创建索引的关键词对象

二、ElasticSearch简介

2.1 什么是ElasticSearch

Elaticsearch,简称为es, es是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。es也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单

2.2 ElasticSearch对比Solr

  • Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能
  • Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式
  • Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提
  • Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于Elasticsearch

三、Elasticsearch 安装

采用docker安装

  1. docker镜像下载
docker pull elasticsearch:5.6.8
  • 1
  1. 安装es容器
docker run -di --name=kkb_es -p 9200:9200 -p 9300:9300 elasticsearch:5.6.8
  • 1

9200端口(Web管理平台端口) 9300(服务默认端口)

  1. 开启远程连接
    elasticsearch从5版本以后默认不开启远程连接,程序直接连接会报错

我们需要修改es配置开启远程连接
登录容器

docker exec -it kkb_es /bin/bash
  • 1

进去config目录

cd config
  • 1

修改elasticsearch.yml文件

若出现vi命令无法识别,则安装该编辑器
设置apt下载源

docker cp ~/sources.list kkb_es:/etc/apt/sources.list
  • 1

安装vim编辑器

apt-get update
apt-get install vim
  • 1
  • 2

安装好之后就可以修改elasticsearch.yml配置文件了

http.host: 0.0.0.0

transport.host: 0.0.0.0
#集群的名称
cluster.name: my-application
#跨域配置
http.cors.enabled: true
http.cors.allow-origin: "*"
network.host: 192.168.249.4
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

配置完毕之后退出容器,重启该容器

docker restart kkb_es
  • 1
  1. 系统参数配置
    因为elasticsearch在启动时会比较占据资源,所以将虚拟机进行系统调优开放更多的资源

修改vi /etc/security/limits.conf,追加如下内容

* soft nofile 65536
* hard nofile 65536
  • 1
  • 2

修改vi /etc/sysctl.conf,追加内容

vm.max_map_count=655360
  • 1

执行下面命令,使修改后的内核参数生效

sysctl -p
  • 1

重启虚拟机,再启动容器,即可远程访问

reboot
  • 1

在这里插入图片描述

四、ElasticSearch的客户端操作

IK分词器

IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始,IKAnalyzer已经推出 了3个大版本。最初,它是以开源项目Lucene为应用主体的,结合词典分词和文法分析算法的中文分词组件。新版本的IKAnalyzer3.0则发展为 面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现

安装

  1. 下载地址https://github.com/medcl/elasticsearch-analysis-ik/releases
    将ik分词器上传到服务器.解压并改名为ik
unzip elasticsearch-analysis-ik-5.6.8.zip
mv elasticsearch ik
  • 1
  • 2

将ik目录拷贝到docker容器的plugins目录下

docker cp ./ik kkb_es:/usr/share/elasticsearch/plugins
  • 1
  1. 测试
    访问 : http://192.168.249.4:9200/_analyze?analyzer=ik_smart&pretty=true&text=我是程序员 出现如下页面

在这里插入图片描述

  • ik_max_word:会将文本做最细粒度的拆分

    比如会将“中华人民共和国人民大会堂”拆分为“中华人民共和国、中华人民、中华、华人、人民共和国、人民、共和国、大会堂、大会、会堂等词语。

  • ik_smart:会做最粗粒度的拆分

    比如会将“中华人民共和国人民大会堂”拆分为中华人民共和国、人民大会堂。

Kibana使用

Kibana 是一款开源的数据分析和可视化平台,它是 Elastic Stack 成员之一,设计用于和 Elasticsearch协作。您可以使用 Kibana 对 Elasticsearch 索引中的数据进行搜索、查看、交互操作。您可以很方便的利用图表、表格及地图对数据进行多元化的分析和呈现

Kibana 可以使大数据通俗易懂。它很简单,基于浏览器的界面便于您快速创建和分享动态数据仪表板来追踪 Elasticsearch 的实时数据变化

下载安装

这里使用docker安装

  1. 镜像安装
docker pull docker.io/kibana:5.6.8
  • 1
  1. 安装kibana容器
docker run -it -d -e ELASTICSEARCH_URL=http://192.168.249.4:9200 --name kibana -p 5601:5601 kibana:5.6.8
  • 1

ELASTICSEARCH_URL=http://192.168.249.4:9200:是指链接的es的地址
restart=always:每次服务都会重启,也就是开启启动
5601:5601:端口号

  1. 测试
    访问http:192.168.249.4:5601如下图所示

在这里插入图片描述

Kibana使用

Kibana具体使用可以查看其他文档,这里不再赘述

ElasticSearch编程操作

创建工程

<dependencies>
    <dependency>
        <groupId>org.elasticsearch</groupId>
        <artifactId>elasticsearch</artifactId>
        <version>5.6.8</version>
    </dependency>
    <dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>transport</artifactId>
    <version>5.6.8</version>
    </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-to-slf4j</artifactId>
            <version>2.9.1</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.24</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.21</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

创建索引index

@Test
    public void createIndex() {
        //1. 配置
        Settings settings = Settings.builder().put("cluster.name", "my-application").build();
        //2. 客户端
        client = new PreBuiltTransportClient(settings);
        client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.249.4"), 9300));
        
        //3. 使用api创建索引
        client.admin().indices().prepareCreate("hello_index").get();

        //4. 关闭client
        client.close();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

索引即相当于数据库

在这里插入图片描述

创建mapping映射

    //创建映射
    @Test
    public void setMappings() throws IOException, ExecutionException, InterruptedException {

        // 添加映射
        /**
         * 格式:
         * "mappings" : {
         }

         }
         "article" : {
         "dynamic" : "false",
         "properties" : {
         "id" : { "type" : "string" },
         "content" : { "type" : "string" },
         "author" : { "type" : "string" }
         }
         }
         }
         */
        XContentBuilder builder = XContentFactory.jsonBuilder()
                .startObject()
                .startObject("article")
                .startObject("properties")
                .startObject("id")
                .field("type", "integer").field("store", "yes")
                .endObject()
                .startObject("title")
                .field("type", "string").field("store", "yes").field("analyzer",
                        "ik_smart")
                .endObject()
                .startObject("content")
                .field("type", "string").field("store", "yes").field("analyzer",
                        "ik_smart")
                .endObject()
                .endObject()
                .endObject()
                .endObject();
// 创建索引
        client.admin().indices().preparePutMapping("hello_index")
                .setType("article").setSource(builder).get();
//释放资源
        client.close();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

mapping映射如下所示

在这里插入图片描述

建立文档document

建立文档(通过XContentBuilder)

    /**
     * 通过XContentBuilder构建Document对象
     * @throws Exception
     */

    @Test
    public void testAddDocument() throws Exception {
        //创建一个client对象
        //创建一个文档对象
        XContentBuilder builder = XContentFactory.jsonBuilder()
                .startObject()
                .field("id", 2l)
                .field("title", "北方入秋速度明显加快 多地降温幅度最多可达10度 22222")
                .field("content", "阿联酋一架客机在纽约机场被隔离 10名乘客病倒")
                .endObject();
        //把文档对象添加到索引库
        client.prepareIndex()
        //设置索引名称
                .setIndex("hello_index")
        //设置type
                .setType("article")
        //设置文档的id,如果不设置的话自动的生成一个id
                .setId("2")
                //设置文档信息
                .setSource(builder)
        //执行操作
                .get();
        //关闭客户端
        client.close();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

查看数据浏览板块里面的hello_index索引,如下图所示

在这里插入图片描述

建立文档(使用Jackson转换实体)

  1. 创建Article实体类
package com.study;

public class Article {
   
        private Integer id;
        private String title;
        private String content;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  1. 添加jackson依赖
<!--            jackson依赖-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.8.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.8.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.8.1</version>
        </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  1. 构造相关方法
    @Test
    public void testAddDocument2() throws Exception {
        //创建一个Article对象
        Article article = new Article();
        //设置对象的属性
        article.setId(3l);
        article.setTitle("MH370坠毁在柬埔寨密林?中国一公司调十颗卫星去拍摄");
        article.setContent("警惕荒唐的死亡游戏!俄15岁少年输掉游戏后用电锯自杀");
        //把article对象转换成json格式的字符串。
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonDocument = objectMapper.writeValueAsString(article);
        System.out.println(jsonDocument);
        //使用client对象把文档写入索引库
        client.prepareIndex("hello_index","article", "3")
                .setSource(jsonDocument, XContentType.JSON)
                .get();
        //关闭客户端
        client.close();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

查看数据浏览中的hello_index相关索引库的信息

在这里插入图片描述

对hello_index索引库添加多条Document对象,方便接下来的操作

    @Test
    public void testAddDocument3() throws Exception {
        for (int i = 4; i < 100; i++) {
            //创建一个Article对象
            Article article = new Article();
            //设置对象的属性
            article.setId(i);
            article.setTitle("女护士路遇昏迷男子跪地抢救:救人是职责更是本能" + i);
            article.setContent("江西变质营养餐事件已致24人就医 多名官员被调查" + i);
            //把article对象转换成json格式的字符串。
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonDocument = objectMapper.writeValueAsString(article);
            //使用client对象把文档写入索引库
            client.prepareIndex("hello_index","article", i + "")
                    .setSource(jsonDocument, XContentType.JSON)
                    .get();
        }
        //关闭客户端
        client.close();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

在这里插入图片描述

查询文档操作

抽取共用方法

构建共用方法,方便后续操作调用使用

 public void search(QueryBuilder queryBuilder) {
        //执行查询得到
        SearchResponse searchResponse = client.prepareSearch("hello_index")
                .setTypes("article")
                .setQuery(queryBuilder)
                .get();

        //处理结果
        SearchHits searchHits = searchResponse.getHits();

        System.out.println("总行数" + searchHits.getTotalHits());


        Iterator<SearchHit>  it = searchHits.iterator();

        while (it.hasNext()){
            SearchHit searchHit = it.next();
            //打印迭代器里面  source-document的json输出
            System.out.println(searchHit.getSourceAsString());
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

termQuery

@Test
    public void testQueryTearm(){
        //构建quertBuilder
        QueryBuilder queryBuilder = QueryBuilders.termQuery("title","女护士");

        search(queryBuilder);

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

testQueryByQueryString

//创建一个QueryBuilder对象
        //参数1:要搜索的字段
        //参数2:要搜索的关键词
        QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("美丽的女护士").defaultField("title");
        search(queryBuilder);
  • 1
  • 2
  • 3
  • 4
  • 5

testQueryByMatchQuery

 @Test
    public void testQueryByMatchQuery() throws Exception {
        //创建一个QueryBuilder对象
        //参数1:要搜索的字段
        //参数2:要搜索的关键词
        QueryBuilder queryBuilder = QueryBuilders.matchQuery("title", "美丽的女护士");
        search(queryBuilder);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

使用文档ID查询文档

 @Test
    public void testSearchById() throws Exception {
        //创建一个client对象
        //创建一个查询对象
        QueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds("1", "2");
        search(queryBuilder);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

查询文档分页操作

@Test
    public void testQueryMatchAllQuery() throws Exception {
        //创建一个QueryBuilder对象
        QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
        //执行查询
        //执行查询得到
        SearchResponse searchResponse = client.prepareSearch("hello_index")
                .setTypes("article")
                .setQuery(queryBuilder)
                //下标起始位置
                .setFrom(0)
                //一页条数
                .setSize(5)
                .get();

        //处理结果
        SearchHits searchHits = searchResponse.getHits();

        System.out.println("总行数" + searchHits.getTotalHits());


        Iterator<SearchHit>  it = searchHits.iterator();

        while (it.hasNext()){
            SearchHit searchHit = it.next();
            //打印迭代器里面  source-document的json输出
            System.out.println(searchHit.getSourceAsString());
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

查询结果高亮操作

代码实现

    @Test
    public void highlightSearchTest() throws Exception {
        QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery("北京市民",
                "title", "content");
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title").field("content");
        highlightBuilder.preTags("<em>");
        highlightBuilder.postTags("</em>");
        //执行查询
        SearchResponse searchResponse = client.prepareSearch("hello_index")
                .setTypes("article")
                .setQuery(queryBuilder)
        //设置高亮信息
                .highlighter(highlightBuilder)
                .get();
        //取查询结果
        SearchHits searchHits = searchResponse.getHits();
        //取查询结果的总记录数
        System.out.println("查询结果总记录数:" + searchHits.getTotalHits());
        //查询结果列表
        Iterator<SearchHit> iterator = searchHits.iterator();
        while(iterator.hasNext()) {
            SearchHit searchHit = iterator.next();
        //取文档的属性
            System.out.println("-----------文档的属性");
            Map<String, Object> document = searchHit.getSource();
            System.out.println(document.get("title"));
            System.out.println(document.get("content"));
            System.out.println("************高亮结果");
            Map<String, HighlightField> highlightFields =
                    searchHit.getHighlightFields();
            // //取title高亮显示的结果
            if (highlightFields.size() <=0) continue;
            for (Map.Entry<String, HighlightField> entry : 
                    highlightFields.entrySet()) {
                System.out.println(entry.getKey() + ":\t" + 
                        Arrays.toString(entry.getValue().getFragments()));
            }
        }
        //关闭client
        client.close();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

Spring Data ElasticSearch

简介

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

入门案例

  1. 导入依赖
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.16.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>


    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <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>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  1. 配置启动器
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class,args);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  1. 配置yml文件
spring:
  data:
    elasticsearch:
      cluster-name: my-application
      cluster-nodes: 192.168.249.4:9300
  • 1
  • 2
  • 3
  • 4
  • 5
  1. 编写实体类
@Document(indexName = "wx_blog", type = "article")
public class Article {
    @Id
    @Field(type = FieldType.Long, store = true)
    private long id;
    @Field(type = FieldType.Text, store = true, analyzer = "ik_smart")
    private String title;
    @Field(type = FieldType.Text, store = true, analyzer = "ik_smart")
    private String content;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  1. 编写Dao

方法命名规则查询的基本语法findBy + 属性 + 关键词 + 连接符

在这里插入图片描述

public interface ArticleRepository extends ElasticsearchRepository<Article,Long> {

   
}
  • 1
  • 2
  • 3
  • 4
  1. 创建测试类
package com.study;

import com.study.dao.ArticleRepository;
import com.study.entity.Article;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runner.notification.RunListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;
import java.util.Optional;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ElaticSearchTest {

    @Autowired
    private ArticleRepository articleRepository;


    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;


    @Test
    public void createIndex(){
        elasticsearchTemplate.createIndex(Article.class);
    }

    @Test
    public void addDocument() throws Exception {
        for (int i = 10; i <= 20; i++) {
        //创建一个Article对象
            Article article = new Article();
            article.setId(i);
            article.setTitle("女护士路遇昏迷男子跪地抢救:救人是职责更是本能" + i);
            article.setContent("这是一个美丽的女护士妹妹" + i);
        //把文档写入索引库
            articleRepository.save(article);
        }
    }


    @Test
    public void deleteDocumentById() throws Exception {
         articleRepository.deleteById(1l);
        //全部删除
//        articleRepository.deleteAll();
    }



    @Test
    public void findAll() throws Exception {
        Iterable<Article> articles = articleRepository.findAll();
        articles.forEach(a-> System.out.println(a));
    }

    @Test
    public void testFindById() throws Exception {
        Optional<Article> optional = articleRepository.findById(10l);
        Article article = optional.get();
        System.out.println(article);
    }
    @Test
    public void testFindByTitle() throws Exception {
        List<Article> list = articleRepository.findByTitle("女护士");
        list.stream().forEach(a-> System.out.println(a));
    }
    @Test
    public void testFindByTitleOrContent() throws Exception {
        Pageable pageable = PageRequest.of(1, 5);
        articleRepository.findByTitleOrContent("title", "女护士", pageable)
                .forEach(a-> System.out.println(a));
    }
    @Test
    public void testNativeSearchQuery() throws Exception {
        //创建一个查询对象
        NativeSearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.queryStringQuery("女护士").defaultField("title"))
                                .withPageable(PageRequest.of(0, 15))
                                .build();
        //执行查询
        List<Article> articleList = elasticsearchTemplate.queryForList(query, Article.class);
        articleList.forEach(a-> System.out.println(a));
    }
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97

聚合查询

实体类

@Document(indexName = "car_index", type = "car")
public class Car {
    @Id
    @Field(type = FieldType.Long, store = true)
    private Long id;
    @Field(type = FieldType.Text, store = true, analyzer = "ik_smart")
    private String name;
    @Field(type = FieldType.Text, store = true, analyzer = "ik_smart", fielddata
            = true)
    private String color;
    @Field(type = FieldType.Text, store = true, analyzer = "ik_smart", fielddata
            = true)
    private String brand;
    @Field(type = FieldType.Double, store = true)
    private Double price;

	public Car(Long id, String name, String brand, String color, Double price) {
        this.id = id;
        this.name = name;
        this.color = color;
        this.brand = brand;
        this.price = price;
    }


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65

Dao


public interface CarDao extends ElasticsearchRepository<Car,Long> {
}
  • 1
  • 2
  • 3

初始化索引库

    @Autowired
    private CarDao carDao;

    @Test
    public void initIndex() {
        carDao.save(new Car(1l, "比亚迪A1", "红色", "比亚迪", 50000d));
        carDao.save(new Car(2l, "比亚迪A2", "白色", "比亚迪", 70000d));
        carDao.save(new Car(3l, "比亚迪A3", "白色", "比亚迪", 80000d));
        carDao.save(new Car(4l, "比亚迪A4", "红色", "比亚迪", 60000d));
        carDao.save(new Car(5l, "比亚迪A5", "红色", "比亚迪", 90000d));
        carDao.save(new Car(6l, "宝马A1", "红色", "宝马", 10000d));
        carDao.save(new Car(7l, "宝马A2", "黑色", "宝马", 20000d));
        carDao.save(new Car(8l, "宝马A3", "黑色", "宝马", 30000d));
        carDao.save(new Car(9l, "宝马A4", "红色", "宝马", 40000d));
        carDao.save(new Car(10l, "宝马A5", "红色", "宝马", 50000d));
        carDao.save(new Car(11l, "奔驰A1", "红色", "奔驰", 10000d));
        carDao.save(new Car(12l, "奔驰A2", "黑色", "奔驰", 20000d));
        carDao.save(new Car(13l, "奔驰A3", "黑色", "奔驰", 30000d));
        carDao.save(new Car(14l, "奔驰A4", "红色", "奔驰", 40000d));
        carDao.save(new Car(15l, "奔驰A5", "红色", "奔驰", 50000d));
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

代码实现

划分桶


    @Test
    public void testQuerySelfAggs(){
        //查询条件的构建器
        NativeSearchQueryBuilder queryBuilder = new
                NativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery());
        //排除所有的字段查询,
        queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{},null));
        //添加聚合条件
        queryBuilder.addAggregation(AggregationBuilders.terms("group_by_color").field("color"));
        //执行查询,把查询结果直接转为聚合page
                AggregatedPage<Car> aggPage = (AggregatedPage<Car>)
                        carDao.search(queryBuilder.build());
        //从所有的聚合中获取对应名称的聚合
        StringTerms agg = (StringTerms) aggPage.getAggregation("group_by_color");
        //从聚合的结果中获取所有的桶信息
        List<StringTerms.Bucket> buckets = agg.getBuckets();
        for (StringTerms.Bucket bucket : buckets) {
            String brand = bucket.getKeyAsString();
            long docCount = bucket.getDocCount();
            System.out.println("color = " + brand+" 总数:"+docCount);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

桶内度量

    @Test
    public void testQuerySelfSubAggs(){
        //查询条件的构建器
        NativeSearchQueryBuilder queryBuilder = new
                NativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery());
        //排除所有的字段查询,
        queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{},null));

        //添加聚合条件
        queryBuilder.addAggregation(AggregationBuilders.terms("group_by_color").field("color")
        .subAggregation(AggregationBuilders.avg("avg_price").field("price")));
        //执行查询,把查询结果直接转为聚合page
        AggregatedPage<Car> aggPage = (AggregatedPage<Car>)
            carDao.search(queryBuilder.build());
    //从所有的聚合中获取对应名称的聚合
    StringTerms agg = (StringTerms) aggPage.getAggregation("group_by_color");
    //从聚合的结果中获取所有的桶信息
    List<StringTerms.Bucket> buckets = agg.getBuckets();
for (StringTerms.Bucket bucket : buckets) {
        String brand = bucket.getKeyAsString();
        long docCount = bucket.getDocCount();
        //取得内部聚合
    InternalAvg avg = (InternalAvg)
            bucket.getAggregations().asMap().get("avg_price");
        System.out.println("brand = " + brand+" 总数:"+docCount+" 平均价格:"+avg.getValue());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/349139?site
推荐阅读
相关标签
  

闽ICP备14008679号