Elasticsearch

第一章 Elasticsearch是什么

映射|弹性搜索指南 [8.4] |弹性的 (elastic.co)

1.1 Elasticsearch是什么

简介
https://www.elastic.co/cn/what-is/elasticsearch
全文搜索属于最常见的需求,开源的 Elasticsearch 是目前全文搜索引擎的首选。
它可以快速地储存、搜索和分析海量数据。维基百科、 Stack Overflow Github 都采用它
Elastic 的底层是开源库 Lucene 。但是,你没法直接用 Lucene ,必须自己写代码去调用它的
接口。 Elastic Lucene 的封装,提供了 REST API 的操作接口,开箱即用。
REST API :天然的跨平台。
官方文档: https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
官方中文: https://www.elastic.co/guide/cn/elasticsearch/guide/current/foreword_id.html
社区中文:
https://es.xiaoleilu.com/index.html
http://doc.codingdict.com/elasticsearch/0/

1.2 全文搜索引擎

 

 1.3 Elasticsearch and Solr

 

 1.4 Elasticsearch or solr

 

 1.5 Elasticsearch应用案例

 第2章 Elasticsearch入门

2.1 ElasticSearch安装

2.1.1 下载软件(用docker部署)

 

mkdir -p /mydata/elasticsearch/config
mkdir -p /mydata/elasticsearch/data
echo "http.host: 0.0.0.0" >> /mydata/elasticsearch/config/elasticsearch.yml
chmod -R 777 /mydata/elasticsearch/ 保证权限
docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch: 7.4.2

 

docker run --name kibana -e ELASTICSEARCH_HOSTS= http://192.168.56.10:9200 -p 5601:5601 \
-d kibana:7.4.2
http://192.168.56.10:9200 一定改为自己虚拟机的地址

 2.2 Elasticsearch基本操作

2.2.1 RESTfull

 2.2.2 客户端安装

 2.2.3 数据格式

 

三、初步检索

1、_cat

GET /_cat/nodes:查看所有节点

GET /_cat/health :查看 es 健康状况
GET /_cat/master :查看主节点
GET /_cat/indices :查看所有索引

2、索引一个文档 (保存)

创建一个索引:PUT product

保存一个数据,保存在哪个索引的哪个类型下,指定用哪个唯一标识
customer 索引下的 external 类型下保存 1 号数据为:
PUT customer/external/1 ;{
"name":"john Doe"
}

3、查询文档

GET customer/external/1

4、更新文档

1、POST customer/external/1/_update

{

"doc":{

"name:":"John Doew"

}

}

2、POST customer/external/1

{

"name":"John Doe2"

}

3、PUT customer/external/1

{

"name":"John Doe"

}

  

 

5、删除文档&索引

DELETE customer/external/1 删除文档

DELETE customer 删除索引

6、bulk批量API

 POST customer/external/_bulk
{"index":{"_id":"1"}}
{"name":"John Doe"}
{"index":{"_id":"2"}}
{"name":"Jane Doe"}

复杂实例:

POST /_bulk
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title":
"My first blog post" }
{ "index": { "_index": "website", "_type": "blog" }}
{ "title":
"My second blog post" }
{ "update": { "_index": "website", "_type": "blog", "_id": "123", "_retry_on_conflict" : 3} }
{ "doc" : {"title" : "My updated blog post"} }

四、进阶检索

1、SearchAPI

 1) 检索信息

2、Query DSL

1)基本语法格式

 

 2)返回部分字段

“_source”:后写上我们想要返回的部分字段

 3)match 匹配查询

match 匹配类型查询,会把查询条件进行分词,然后进行查询,多个词条之间是 or 的关系
Postman 中,向 ES 服务器发 GET 请求 : http://127.0.0.1:9200/student/_search

 

 4)match_phrase 短语匹配

 5)multi_match多字段匹配

 6)bool复合查询

`bool` 把各种其它查询通过 `must` (必须 )、 `must_not` (必须不)、 `should` (应该)的方
式进行组合

must:

 

 should:

 must_not:

 

 

 7) filter 结果过滤

 8) term(和match一样,是用来匹配属性值的,精确匹配)、terms(多关键字精确匹配查询)

term 查询,精确的关键词匹配查询,不对查询条件进行分词。
Postman 中,向 ES 服务器发 GET 请求 : http://127.0.0.1:9200/student/_search

 

 9)aggregations(执行聚合)

 

 

 

 

 

 

 

10)范围查询 range

11)模糊查询 fuzzy

 

12)单字段排序

 13)多字段排序

 13)高亮查询

 

 

 15)分页查询

 16)聚合查询

 

 

 

 

 17)桶聚合查询

 

 

 3、Mapping(映射)

1)字段类型

 

 

映射数据说明:
字段名:任意填写,下面指定许多属性,例如: title subtitle images price
type :类型, Elasticsearch 中支持的数据类型非常丰富,说几个关键的:
  String 类型,又分两种:
   text :可分词
   keyword :不可分词,数据会作为完整字段进行匹配
  Numerical :数值类型,分两类
 基本数据类型: long integer short byte double float half_float
 浮点数的高精度类型: scaled_float
  Date :日期类型
  Array :数组类型
  Object :对象
  index :是否索引,默认为 true ,也就是说你不进行任何配置,所有字段都会被索引。
    true :字段会被索引,则可以用来进行搜索
    false :字段不会被索引,不能用来搜索
  store :是否将数据进行独立存储,默认为 false
   原始的文本会存储在 _source 里面,默认情况下其他提取出来的字段都不是独立存储
   的,是从 _source 里面提取出来的。当然你也可以独立的存储某个字段,只要设置
  "store": true 即可,获取独立存储的字段要比从 _source 中解析快得多,但是也会占用
更多的空间,所以要根据实际业务需求来设置。
  analyzer :分词器,这里的 ik_max_word 即使用 ik 分词器 , 后面会有专门的章节学习

 2)映射

 1.查看mapping信息:

GET bank/_mapping
2.修改mapping信息:

 3)新版本改变

(1)创建映射

1、创建索引并指定映射

 2、添加新的字段映射

 3、更新映射(记住,映射是不能更新的,我们只能创建一个新的索引并指定我们想要的映射,然后进行数据迁移)

 4、数据迁移

 

 # 数据迁移
POST _reindex
{
  "source": {
    "index": "product"  #旧索引
  },
  "dest":{
    "index":"gulimall_product" #新索引
  }
}

 4、分词

 

 https://github.com/medcl/elasticsearch-analysis-ik/releases?after=v6.4.2

https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-anal
ysis-ik-7.4.2.zip

 

 

 

3 )、自定义词库
修改 /usr/share/elasticsearch/plugins/ik/config/ 中的 IKAnalyzer.cfg.xml
/usr/share/elasticsearch/plugins/ik/config
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict"></entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<entry key="remote_ext_dict">http://192.168.128.130/fenci/myword.txt</entry>
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
原来的 xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment><!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict"></entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

 

五、java API操作

 https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html

1、创建Maven项目,导入依赖

<dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>7.4.2</version>
        </dependency>
        <!-- elasticsearch 的客户端 -->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.4.2</version>
        </dependency>
        <!-- elasticsearch 依赖 2.x 的 log4j -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.8.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.8.2</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.9</version>
        </dependency>
        <!-- junit 单元测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

2、创建ES的REST高级客户端对象,用来操作ES

/**
 * ES的高级REST客户端对象
 */
public class ESRestHighLevelClient {
    public static void main(String[] args) throws Exception {
        //创建ES的REST高级客户端对象
        RestHighLevelClient restHighLevelClient=new RestHighLevelClient(
                RestClient.builder(new HttpHost("192.168.160.139",9200,"http"))
        );
        System.out.println(restHighLevelClient);
        //关闭客户端
        restHighLevelClient.close();

    }
}

3、索引操作

ES 服务器正常启动后,可以通过 Java API 客户端对象对 ES 索引进行操作

3.1 创建索引

 /**
         * 1)创建索引-请求对象
         */
        CreateIndexRequest indexRequest=new CreateIndexRequest("user");//user是索引的名称
        /**
         * 2)发送请求,获取响应
         */
        CreateIndexResponse indexResponse=restHighLevelClient.indices().create(indexRequest, RequestOptions.DEFAULT);
        /**
         * 3)获取响应结果
         */
        System.out.println("操作状态:"+indexResponse.isAcknowledged());

3.2 查看索引

 /**
     * 查看索引
     */
    @Test
    void getIndex() throws IOException {
        /**
         * 1)查看索引——请求对象
         */
        GetIndexRequest indexRequest=new GetIndexRequest("user");
        /**
         * 2)发送请求——获取响应
         */
        GetIndexResponse indexResponse = client.indices().get(indexRequest, RequestOptions.DEFAULT);
        /**
         * 3)获取响应结果
         */
        indexResponse.getIndices();
        indexResponse.getAliases();
        indexResponse.getMappings();
    }

3.3 删除索引

/**
     * 删除索引
     */
    @Test
    void deleteIndex() throws IOException {
        /**
         * 1)删除索引——请求对象
         */
        DeleteIndexRequest indexRequest=new DeleteIndexRequest("user");
        /**
         * 2)发送请求——获取响应
         */
        AcknowledgedResponse deleteRepose = client.indices().delete(indexRequest, RequestOptions.DEFAULT);
        /**
         * 3)获取响应结果
         */
        System.out.println(deleteRepose.isAcknowledged());

    }

4、文档操作

4.1 新增文档

创建数据模型

package com.wangbijun.es_project.eneity;

import lombok.Data;

@Data
public class User {
    private String  name;
    private Integer age;
    private String sex;
}

创建数据并添加到文档中

    /**
     * 创建数据,并将数据添加到文档中
     */
    @Test
    void addDataToDocument() throws IOException {
        //新增文档——请求对象
        IndexRequest indexRequest=new IndexRequest();
        //设置索引及唯一性标识
        indexRequest.index("user").id("1001");
        //创建数据对象
        User user=new User();
        user.setName("王碧军");
        user.setAge(20);
        user.setSex("女");
        //将对象转换成JSON格式
        ObjectMapper objectMapper=new ObjectMapper();
        String asString = objectMapper.writeValueAsString(user);
        //将文档数据添加到请求对象中
        indexRequest.source(asString, XContentType.JSON);
        //客户端发送请求,获取响应对象
        IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
        //打印结果信息
        System.out.println("_index:"+indexResponse.getIndex());
        System.out.println("_id:"+indexResponse.getId());
        System.out.println("_result:"+indexResponse.getResult());
    }

4.2 修改文档 

    /**
     * 修改文档
     */
    @Test
    void updateDocument() throws IOException {
        //修改文档——创建请求对象
        UpdateRequest updateRequest=new UpdateRequest();
        //配置修改参数
        updateRequest.index("user").id("1001");
        //设置请求体,对数据进行修改
        updateRequest.doc(XContentType.JSON,"sex","男");
        //客户端发送请求,获取响应对象
        UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);
        //打印响应结果
        System.out.println("_index:"+updateResponse.getIndex());
        System.out.println("_id:"+updateResponse.getId());
        System.out.println("_result:"+updateResponse.getResult());

    }

4.3 查询文档

    /**
     * 查询文档
     */
    @Test
    void getDocument() throws IOException {
        //查询文档——请求对象
        GetRequest getRequest=new GetRequest();
        //配置查询参数
        getRequest.index("user").id("1001");
        //客户端发送请求,获取响应对象
        GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
        //打印查询结果
        System.out.println("_index:"+getResponse.getIndex());
        System.out.println("_id:"+getResponse.getId());
        System.out.println("_source:"+getResponse.getSourceAsString());
    }

 4.4 删除文档


    /**
     * 删除文档
     */
    @Test
    void deleteDocument() throws IOException {
        //删除文档——请求对象
        DeleteRequest deleteRequest=new DeleteRequest();
        //配置删除参数
        deleteRequest.index("user").id("1001");
        //客户端发送请求,获取响应对象
        DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);
    //打印响应结果
        System.out.println(deleteResponse.toString());
}

4.5 批量操作

批量新增:

/**
 * 批量增加
 */
 @Test
    void bulkAdd() throws IOException {
    //批量新增——请求对象
     BulkRequest bulkRequest=new BulkRequest();
     //设置请求体,将要新增的数据封装对请求对象中
     User user1=new User();
     User user2=new User();
     User user3=new User();
     user1.setName("王碧军1");
     user1.setAge(20);
     user1.setSex("女");
     user2.setName("王碧军2");
     user2.setAge(20);
     user2.setSex("女");
     user3.setName("王碧军3");
     user3.setAge(20);
     user3.setSex("女");
     ObjectMapper objectMapper=new ObjectMapper();
     String u1 = objectMapper.writeValueAsString(user1);
     String u2 = objectMapper.writeValueAsString(user2);
     String u3 = objectMapper.writeValueAsString(user3);
     bulkRequest.add(new IndexRequest()
                     .index("user")
                     .id("1001")
                     .source(u1,XContentType.JSON));
     bulkRequest.add(new IndexRequest()
             .index("user")
             .id("1002")
             .source(u2,XContentType.JSON));
     bulkRequest.add(new IndexRequest()
             .index("user")
             .id("1003")
             .source(u3,XContentType.JSON));
     //客户端发送请求,获取响应对象
     BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
     //打印响应对象
     System.out.println(bulkResponse.toString());
 }

批量删除:

/**
     * 批量删除对象
     */
    @Test
    void bulkDelete() throws IOException {
        BulkRequest bulkRequest=new BulkRequest();
        bulkRequest.add(new DeleteRequest()
                .index("user")
                .id("1001")
        );
        bulkRequest.add(new DeleteRequest()
                .index("user")
                .id("1002")
        );
        bulkRequest.add(new DeleteRequest()
                .index("user")
                .id("1003")
        );
        //客户端发送请求,获取响应对象
        BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
        //打印结果
        System.out.println(bulkResponse);

    }

 5、高级查询

5.1 请求体查询

查询所有索引数据

 /**
     * 查询所有索引数据
     */
    @Test
    void searchAllIndex() throws IOException {
        //创建搜索请求体对象
        SearchRequest searchRequest=new SearchRequest();
        //指定要查询的索引
        searchRequest.indices("user");
        //构建查询的请求体
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
        //全匹配查询
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        //将请求体放到请求对象中
        searchRequest.source(sourceBuilder);
        //客户端发送请求,获取响应结果
        SearchResponse response=client.search(searchRequest,RequestOptions.DEFAULT);
        //打印请求结果
        SearchHits hits = response.getHits();
        for (SearchHit hit : hits.getHits()) {
            System.out.println(hit.getSourceAsString());
        }
    }

term查询,查询条件为关键字

      /**
     * term查询
     */
    @Test
    void termQuery() throws IOException {
        //创建搜索请求体对象
        SearchRequest searchRequest=new SearchRequest();
        //指定要操作的索引
        searchRequest.indices("user");
        //构建查询的请求体
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.termQuery("age","20"));
        searchRequest.source(sourceBuilder);
        //客户端发送请求,获取响应结果
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();
        for (SearchHit hit : hits.getHits()) {
            System.out.println(hit.getSourceAsString());
        }
    }

分页查询

  /**
     * 分页查询
     */
    @Test
    void pageSearch() throws IOException {
        //创建搜索请求体对象
        SearchRequest searchRequest=new SearchRequest();
        searchRequest.indices("user");
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        sourceBuilder.from(0);
        sourceBuilder.size(2);
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse=client.search(searchRequest,RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();
        for (SearchHit hit : hits.getHits()) {
            System.out.println(hit.getSourceAsString());
        }

    }

数据排序

  /**
     * 数据排序
     */
    @Test
    void SortSearch() throws IOException {
        SearchRequest searchRequest=new SearchRequest();
        searchRequest.indices("user");
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        sourceBuilder.sort("age", SortOrder.ASC);
        searchRequest.source(sourceBuilder);
        SearchResponse searchReponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchReponse.getHits();
        for (SearchHit hit : hits.getHits()) {
            System.out.println(hit.getSourceAsString());
        }

    }

过滤字段

  /**
     * 数据排序
     */
    @Test
    void SortSearch() throws IOException {
        SearchRequest searchRequest=new SearchRequest();
        searchRequest.indices("user");
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        sourceBuilder.sort("age", SortOrder.ASC);
        searchRequest.source(sourceBuilder);
        SearchResponse searchReponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchReponse.getHits();
        for (SearchHit hit : hits.getHits()) {
            System.out.println(hit.getSourceAsString());
        }

    }

Bool查询

/**
 * Bool查询
 */
@Test
    void boolSearch() throws IOException {
    SearchRequest searchRequest=new SearchRequest();
    searchRequest.indices("user");
    SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    boolQueryBuilder.must(QueryBuilders.matchQuery("name","王碧军"));
    boolQueryBuilder.mustNot(QueryBuilders.termsQuery("age","23"));
    boolQueryBuilder.should(QueryBuilders.matchQuery("sex","女"));
    sourceBuilder.query(boolQueryBuilder);
    searchRequest.source(sourceBuilder);
    SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
    SearchHits hits = searchResponse.getHits();
    for (SearchHit hit : hits.getHits()) {
        System.out.println(hit.getSourceAsString());
    }
}

范围查询

 

 模糊查询

 5.2 高亮查询

/**
 * 高亮查询
 */
@Test
void HighLightSearch() throws IOException {
    SearchRequest searchRequest=new SearchRequest().indices("user");
    SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
    sourceBuilder.query(QueryBuilders.termsQuery("name","王碧军1"));
    //构建高亮字段
    HighlightBuilder highlightBuilder=new HighlightBuilder();
    highlightBuilder.preTags("<font color='red'>");//设置前缀标签
    highlightBuilder.postTags("</font>");//设置后缀标签
    highlightBuilder.field("name");//设置高亮字段
    sourceBuilder.highlighter(highlightBuilder);
    searchRequest.source(sourceBuilder);
    SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
    SearchHits hits = searchResponse.getHits();
    for (SearchHit hit : hits.getHits()) {
        System.out.println(hit.getSourceAsString());
    }

}

5.3 聚合查询

最大年龄 

 

 分组统计

六、Elasticsearch集群

https://blog.csdn.net/li1669852599/article/details/109103015

七、Elasticsearch 进阶

7.1 核心概念

7.1.1 索引(Index)

 7.1.2 类型(Type)

 7.1.3 文档(Document)

 7.1.4 字段(Field)

 7.1.5 映射(Mapping)

 7.1.6 分片(Shards)

 7.1.7 副本(Replicas)

 

 7.1.8 分配(Allocation)

7.2 系统架构

 

 7.3 分布式集群

7.3.1 单节点集群

 

 

 7.3.2 故障转移

 

 7.3.3 水平扩容

 

 

 

 

 

 

 7.3.4 应对故障

 

 

 7.4 路由计算

 

 7.5 分片控制

 

 

 7.5.1 写流程

 

 

 

 7.5.2 读流程

 

 7.5.3 更新流程

 

 

 7.5.4 多文档操作流程

 

 

 7.6 分片原理

 7.6.1 倒排索引

 

 

 

 

 

 

 

 7.6.2 文档搜索

 7.6.3 动态更新索引

 

 

 

 

 7.6.4 近实时搜索

 

 

 

{
"settings": {
"refresh_interval": "30s"
}
}

 refresh_interval 可以在既存索引上进行动态更新。 在生产环境中,当你正在建立一个大的

新索引时,可以先关闭自动刷新,待开始使用该索引时,再把它们调回来
# 关闭自动刷新
PUT /users/_settings
{ "refresh_interval": -1 }
# 每一秒刷新
PUT /users/_settings
{ "refresh_interval": "1s" }

 7.6.5 持久化变更

 

 

 

 

 

 

 

 

 

 

 

 

 7.7 文档分析

 

 7.7.1 内置分析器

 

 7.7.2 分析器使用场景

 

 7.7.3 测试分析器

 

 

 7.7.4 指定分析器

 

 7.7.5 IK分词器

 

 

 

 

 

 

 

 7.7.6 自定义分析器

 

 

 

 

 

 7.8 文档处理

7.8.1 文档冲突

 

 

 7.8.2 乐观并发控制

 

 

 7.8.3 外部系统版本控制

 

 

 7.5 Kibana

docker部署

 八、Elasticsearch集成

8.1 Spring Data框架集成

8.1.1 Spring Data 框架介绍

 

 8.1.2 spring data elasticsearch介绍

 8.1.3 spring data elasticsearch版本对比

 

 8.1.4 框架集成

 2. 修改 pom 文件,增加依赖关系

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-parent</artifactId>
 <version>2.3.6.RELEASE</version>
 <relativePath/>
 </parent>
 <groupId>com.atguigu.es</groupId>
 <artifactId>springdata-elasticsearch</artifactId>
 <version>1.0</version>
 <properties>
 <maven.compiler.source>8</maven.compiler.source>
 <maven.compiler.target>8</maven.compiler.target>
 </properties>
 <dependencies>
 <dependency>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok</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-devtools</artifactId>
 <scope>runtime</scope>
 <optional>true</optional>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-test</artifactId>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-test</artifactId>
 </dependency>
 <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-test</artifactId>
 </dependency>
 </dependencies>
</project>

 3. 增加配置文件application.yml

# es 服务地址
elasticsearch.host=127.0.0.1
# es 服务端口
elasticsearch.port=9200
# 配置日志级别,开启 debug 日志
logging.level.com.atguigu.es=debug

 5. 数据实体类

package com.atguigu.es;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Product {
 private Long id;//商品唯一标识
 private String title;//商品名称
 private String category;//分类名称
 private Double price;//商品价格
 private String images;//图片地址
}

6. 配置类
ElasticsearchRestTemplate spring-data-elasticsearch 项目中的一个类,和其他 spring 项目中的 template
类似。
在新版的 spring-data-elasticsearch 中, ElasticsearchRestTemplate 代替了原来的 ElasticsearchTemplate
原因是 ElasticsearchTemplate 基于 TransportClient TransportClient 即将在 8.x 以后的版本中移除。所 以,我们推荐使用 ElasticsearchRestTemplate
ElasticsearchRestTemplate 基 于 RestHighLevelClient 客户端的。需要自定义配置类,继承
AbstractElasticsearchConfiguration ,并实现 elasticsearchClient() 抽象方法,创建 RestHighLevelClient 对 象
package com.atguigu.es;
import lombok.Data;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import 
org.springframework.data.elasticsearch.config.AbstractElasticsearchConfigura
tion;
@ConfigurationProperties(prefix = "elasticsearch")
@Configuration
@Data
public class ElasticsearchConfig extends AbstractElasticsearchConfiguration {
 private String host ;
 private Integer port ;
 //重写父类方法
 @Override
 public RestHighLevelClient elasticsearchClient() {
 RestClientBuilder builder = RestClient.builder(new HttpHost(host, port));
 RestHighLevelClient restHighLevelClient = new 
RestHighLevelClient(builder);
 return restHighLevelClient;
 } }
7. DAO 数据访问对象
package com.atguigu.es;
import 
org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ProductDao extends ElasticsearchRepository<Product,Long> {
}
8. 实体类映射操作
package com.atguigu.es;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Document(indexName = "shopping", shards = 3, replicas = 1)
public class Product {
 //必须有 id,这里的 id 是全局唯一的标识,等同于 es 中的"_id"
 @Id
 private Long id;//商品唯一标识
 /**
 * type : 字段数据类型
 * analyzer : 分词器类型
 * index : 是否索引(默认:true)
 * Keyword : 短语,不进行分词
 */
 @Field(type = FieldType.Text, analyzer = "ik_max_word")
 private String title;//商品名称
 @Field(type = FieldType.Keyword)
 private String category;//分类名称
 @Field(type = FieldType.Double)
 private Double price;//商品价格
 @Field(type = FieldType.Keyword, index = false)
 private String images;//图片地址
}
9. 索引操作
package com.atguigu.es;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringDataESIndexTest {
 //注入 ElasticsearchRestTemplate
 @Autowired
 private ElasticsearchRestTemplate elasticsearchRestTemplate;
 //创建索引并增加映射配置
 @Test
 public void createIndex(){
 //创建索引,系统初始化会自动创建索引
 System.out.println("创建索引");
 }
 @Test
 public void deleteIndex(){
 //创建索引,系统初始化会自动创建索引
 boolean flg = elasticsearchRestTemplate.deleteIndex(Product.class);
 System.out.println("删除索引 = " + flg);
 } }
10. 文档操作
package com.atguigu.es;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.ArrayList;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringDataESProductDaoTest {
 @Autowired
 private ProductDao productDao;
 /**
 * 新增
 */
 @Test
 public void save(){
 Product product = new Product();
 product.setId(2L);
 product.setTitle("华为手机");
 product.setCategory("手机");
 product.setPrice(2999.0);
 product.setImages("http://www.atguigu/hw.jpg");
 productDao.save(product);
 }
 //修改
 @Test
 public void update(){
 Product product = new Product();
 product.setId(1L);
 product.setTitle("小米 2 手机");
 product.setCategory("手机");
 product.setPrice(9999.0);
 product.setImages("http://www.atguigu/xm.jpg");
 productDao.save(product);
 }
 //根据 id 查询
 @Test
 public void findById(){
 Product product = productDao.findById(1L).get();
 System.out.println(product);
 }
 //查询所有
@Test
 public void findAll(){
 Iterable<Product> products = productDao.findAll();
 for (Product product : products) {
 System.out.println(product);
 }
 }
 //删除
 @Test
 public void delete(){
 Product product = new Product();
 product.setId(1L);
 productDao.delete(product);
 }
 //批量新增
 @Test
 public void saveAll(){
 List<Product> productList = new ArrayList<>();
 for (int i = 0; i < 10; i++) {
 Product product = new Product();
 product.setId(Long.valueOf(i));
 product.setTitle("["+i+"]小米手机");
 product.setCategory("手机");
 product.setPrice(1999.0+i);
 product.setImages("http://www.atguigu/xm.jpg");
 productList.add(product);
 }
 productDao.saveAll(productList);
 }
 //分页查询
 @Test
 public void findByPageable(){
 //设置排序(排序方式,正序还是倒序,排序的 id)
 Sort sort = Sort.by(Sort.Direction.DESC,"id");
 int currentPage=0;//当前页,第一页从 0 开始,1 表示第二页
 int pageSize = 5;//每页显示多少条
 //设置查询分页
 PageRequest pageRequest = PageRequest.of(currentPage, pageSize,sort);
 //分页查询
 Page<Product> productPage = productDao.findAll(pageRequest);
 for (Product Product : productPage.getContent()) {
 System.out.println(Product);
 }
 } }

11. 文档搜索
package com.atguigu.es;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringDataESSearchTest {
 @Autowired
 private ProductDao productDao;
 /**
 * term 查询
 * search(termQueryBuilder) 调用搜索方法,参数查询构建器对象
 */
 @Test
 public void termQuery(){
 TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", "
小米");
 Iterable<Product> products = productDao.search(termQueryBuilder);
 for (Product product : products) {
 System.out.println(product);
 }
 }
 /**
 * term 查询加分页
 */
 @Test
 public void termQueryByPage(){
 int currentPage= 0 ;
 int pageSize = 5;
 //设置查询分页
 PageRequest pageRequest = PageRequest.of(currentPage, pageSize);
 TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", "
小米");
 Iterable<Product> products = 
productDao.search(termQueryBuilder,pageRequest);
 for (Product product : products) {
 System.out.println(product);
 }
 } }

九、Elasticsearch 优化

9.1 硬件选择

 

 9.2 分片策略

9.2.1 合理设置分片数

 

 

 9.2.2 推迟分片分配

 9.3 路由选择

 

 9.4 写入速度优化

 9.4.1 批量数据提交

 9.4.2 优化存储设备

 9.4.3 合理使用合并

 9.4.4 减少Refresh的次数

 9.4.5 加大flush设置

 9.4.6 减少副本的数量

 9.5 内存设置

 

 9.6 重要配置

 

 

 十、Elasticsearch 面试题

10.1 为什么要使用Elastisearch

 10.2 Elasticsearch的master选举流程

 10.3 Elasticsearch集群脑裂问题

 

 10.4 Elasticsearch 索引文档的流程

 

 10.5 Elasticsearch更新和删除文档的流程

 

 10.6 Elasticsearch搜索流程

 

 10.7 Elasticsearch在部署时,对Linux的设置有哪些优化方法

 

 

 10.8 GC方面,在使用Elasticsearch时要注意什么

 

 10.9 Elasticsearch对于大数据量(上亿量级)的聚合如何实现

 10.10 在并发情况下,Elasticsearch如何保证读写一致

 10.11 如何监控Elasticsearch集群状态

 10.12 是否了解字典树

 

 

 10.13 Elasticsearch中的集群、节点、索引、文档、类型是什么?

 10.14 Elasticsearch中的倒排索引是什么

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值