1.什么是elasticsearch
    elasticsearch是一款非常强大的开源搜索引擎 目前市占率第一
    可以应对海量且复杂的搜索
    也可用来实现日志统计 分析 系统监控等功能

    2.ELK技术栈
    elasticsearch结合kibana Logstash Beats

    3.elasticsearch底层是根据Lucene来实现的
    Lucene是一个Java语言的搜索引擎类库 是Apache公司的顶级项目

    4.倒排索引
    这个概念基于MySQL的正向索引而来 。
    正向索引即逐行扫描全表。
    倒排索引中有两个非常重要的特点
    ①文档:用来搜索的数据 其中每条数据就是一个文档
    ②词条:
    对文档搜索或用户搜索数据 利用某种算法分词 得到具备含义的词语就是词条

    创建倒排索引步骤:
    1.将每一个文档的数据利用分词算法 得到一个个的词条
    2.创建表 每行数据包括词条 词条所在文档id 位置等信息
    3.因为词条的唯一性 可以给词条创建索引 例如hash表结构索引
    5.索引库操作
    1.mapping映射属性
    mapping是对索引库中文档的约束,常见的mapping属性包括:

    • type:字段数据类型,常见的简单类型有:
      • 字符串:text(可分词的文本)、keyword(精确值,例如:品牌、国家、ip地址)
      • 数值:long、integer、short、byte、double、float、
      • 布尔:boolean
      • 日期:date
      • 对象:object
    • index:是否创建索引,默认为true
    • analyzer:使用哪种分词器
    • properties:该字段的子字段

    6.索引库的CRUD
    这里我们统一使用Kibana编写DSL的方式来书写

    6.1创建索引库和映射

    • 请求方式:PUT
    • 请求路径:/索引库名,可以自定义
    • 请求参数:mapping映射

    格式:

    1. PUT /索引库名称
    2. {
    3. "mappings": {
    4. "properties": {
    5. "字段名":{
    6. "type": "text",
    7. "analyzer": "ik_smart"
    8. },
    9. "字段名2":{
    10. "type": "keyword",
    11. "index": "false"
    12. },
    13. "字段名3":{
    14. "properties": {
    15. "子字段": {
    16. "type": "keyword"
    17. }
    18. }
    19. },
    20. // ...略
    21. }
    22. }
    23. }

    6.2查询索引库

    • 请求方式:GET
    • 请求路径:/索引库名
    • 请求参数:无

    格式

    1. GET /索引库名

    6.3修改索引库
    索引库一旦创建,无法修改mapping
    语法说明

    PUT /索引库名/_mapping
    {
      "properties": {
        "新字段名":{
          "type": "integer"
        }
      }
    }
    

    6.4删除索引库
    语法:

    • 请求方式:DELETE
    • 请求路径:/索引库名
    • 请求参数:无

    格式:

    DELETE /索引库名
    

    7.文档操作
    7.1新增文档
    语法:

    POST /索引库名/_doc/文档id
    {
        "字段1": "值1",
        "字段2": "值2",
        "字段3": {
            "子属性1": "值3",
            "子属性2": "值4"
        },
        // ...
    }
    

    7.2.查询文档
    语法:

    GET /{索引库名称}/_doc/{id}
    GET /heima/_doc/1
    

    7.3删除文档

    DELETE /{索引库名}/_doc/id值
    DELETE /heima/_doc/1
    

    7.4修改文档
    7.4.1全量修改:直接覆盖原来的文档

    PUT /{索引库名}/_doc/文档id
    {
        "字段1": "值1",
        "字段2": "值2",
        // ... 略
    }
    

    7.4.2.增量修改

    POST /{索引库名}/_update/文档id
    {
        "doc": {
             "字段名": "新的值",
        }
    }
    

    8.RestAPI
    代码分为三步:

    • 1)创建Request对象。因为是创建索引库的操作,因此Request是CreateIndexRequest。
    • 2)添加请求参数,其实就是DSL的JSON参数部分。因为json字符串很长,这里是定义了静态字符串常量MAPPING_TEMPLATE,让代码看起来更加优雅。
    • 3)发送请求,client.indices()方法的返回值是IndicesClient类型,封装了所有与索引库操作有关的方法。

    8.1创建索引库

    @Test
    void createHotelIndex() throws IOException {
        // 1.创建Request对象
        CreateIndexRequest request = new CreateIndexRequest("hotel");
        // 2.准备请求的参数:DSL语句
        request.source(MAPPING_TEMPLATE, XContentType.JSON);
        // 3.发送请求
        client.indices().create(request, RequestOptions.DEFAULT);
    }
    

    8.2删除索引库

    @Test
    void testDeleteHotelIndex() throws IOException {
        // 1.创建Request对象
        DeleteIndexRequest request = new DeleteIndexRequest("hotel");
        // 2.发送请求
        client.indices().delete(request, RequestOptions.DEFAULT);
    }
    

    8.3判断索引库是否存在

    @Test
    void testExistsHotelIndex() throws IOException {
        // 1.创建Request对象
        GetIndexRequest request = new GetIndexRequest("hotel");
        // 2.发送请求
        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
        // 3.输出
        System.err.println(exists ? "索引库已经存在!" : "索引库不存在!");
    }
    

    9.文档操作

            private RestHighLevelClient client;
        @Autowired
        private HotelService hotelService;
        //添加文档
        @Test
        void testAddDocument() throws IOException {
            //根据id查询酒店数据
            Hotel hotel = hotelService.getById(60363L);
            //转换为文档类型
            HotelDoc hotelDoc = new HotelDoc(hotel);
            //1.准备Request对象
            IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());
            //2.准备Json文档
            request.source(JSON.toJSONString(hotelDoc),XContentType.JSON);
            //3.发送请求
            client.index(request,RequestOptions.DEFAULT);
        }
        //查询文档
        @Test
        void testGetDocumentById() throws IOException {
            //1.准备Request
            GetRequest request = new GetRequest("hotel", "60363");
            //2.发送请求,得到响应
            GetResponse response = client.get(request, RequestOptions.DEFAULT);
            //3.解析相应结果
            String json = response.getSourceAsString();
    
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            System.out.println(hotelDoc);
        }
    //修改文档
        @Test
        void testUpdateDocument() throws IOException {
            //1.准备Request
            UpdateRequest request = new UpdateRequest("hotel", "60363");
            //2.准备请求参数
            request.doc(
                    "price","999",
                    "starName","四星级"
            );
            //3.发送请求
            client.update(request,RequestOptions.DEFAULT);
        }
    //删除文档
        @Test
        void testDeleteDoc() throws IOException {
            //1.准备Request
            DeleteRequest request = new DeleteRequest("hotel", "60363");
    
            //2.发送请求
            client.delete(request,RequestOptions.DEFAULT);
        }
    //批量添加文档
        @Test
        void testBulkRequest() throws IOException {
            //批量查询酒店数据
            List<Hotel> hotels = hotelService.list();
    
            //1.创建Request
            BulkRequest request = new BulkRequest();
            //2.准备参数 添加多个新增的Request
            for (Hotel hotel : hotels) {
                HotelDoc hotelDoc = new HotelDoc(hotel);
                request.add(new IndexRequest("hotel")
                        .id(hotelDoc.getId().toString())
                        .source(JSON.toJSONString(hotelDoc),XContentType.JSON)
                );
            }
            //3.发送请求
            client.bulk(request,RequestOptions.DEFAULT);
        }
            //创建连接
        @BeforeEach
        void setUp(){
            this.client = new RestHighLevelClient(RestClient.builder(
                    HttpHost.create("http://192.168.18.99:9200")
            ));
        }
            //释放资源
        @AfterEach
        void tearDowm() throws IOException {
            this.client.close();
          }