zoukankan      html  css  js  c++  java
  • ElasticSearch

    ElasticSearch

    1、概述

    ​ Elasticsearch 是一个分布式可扩展的实时搜索和分析引擎,一个建立在全文搜索引擎 Apache Lucene(TM) 基础上的搜索引擎.当然 Elasticsearch 并不仅仅是 Lucene 那么简单,它不仅包括了全文搜索功能,还可以进行以下工作:

    • 分布式实时文件存储,并将每一个字段都编入索引,使其可以被搜索。
    • 实时分析的分布式搜索引擎。
    • 可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据。

    基本概念

    先说Elasticsearch的文件存储,Elasticsearch是面向文档型数据库,一条数据在这里就是一个文档,用JSON作为文档序列化的格式,比如下面这条用户数据:

    {
        "name" :     "John",
        "sex" :      "Male",
        "age" :      25,
        "birthDate": "1990/05/01",
        "about" :    "I love to go rock climbing",
        "interests": [ "sports", "music" ]
    }
    

    用Mysql这样的数据库存储就会容易想到建立一张User表,有balabala的字段等,在Elasticsearch里这就是一个文档,当然这个文档会属于一个User的类型,各种各样的类型存在于一个索引当中。这里有一份简易的将Elasticsearch和关系型数据术语对照表:

    关系数据库       ⇒ 数据库        ⇒ 表          ⇒ 行              ⇒ 列(Columns)
    
    Elasticsearch  ⇒ 索引(Index)   ⇒ 类型(type)  ⇒ 文档(Docments)  ⇒ 字段(Fields)  
    

    一个 Elasticsearch 集群可以包含多个索引(数据库),也就是说其中包含了很多类型(表)。这些类型中包含了很多的文档(行),然后每个文档中又包含了很多的字段(列)。Elasticsearch的交互,可以使用Java API,也可以直接使用HTTP的Restful API方式,比如我们打算插入一条记录,可以简单发送一个HTTP的请求:

    PUT /megacorp/employee/1  
    {
        "name" :     "John",
        "sex" :      "Male",
        "age" :      25,
        "about" :    "I love to go rock climbing",
        "interests": [ "sports", "music" ]
    }
    

    更新,查询也是类似这样的操作,具体操作手册可以参见Elasticsearch权威指南

    ElasticSearch的搜索是采用的倒排索引,具体的看倒排索引

    2、ik分词器

    什么是ik分词器?

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

    IK提供了两个分词算法:ik_smart和ik_max_word,其中ik_smart为最少划分,ik_max_word为最细度划分。

    测试:

    ik_smart最少划分

    ik_max_word最细度划分

    我们还使用过程中,还可能遇到ik词中没有”张锦豪“这个词,把它划分成了"张","锦",”豪“。

    这时候我们可以在ik分词器中的配置文件添加自己所需要的词。

    然后查询出来的就是”张锦豪“

    注意:类型为keyword类型的字段不能被分词器解析。

    3、Restful风格

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

    基本的Rest命令说明:

    method url 描述
    put localhost:9200/索引名称/类型名称/文档id 创建文档(指定id)
    post localhost:9200/索引名称/类型名称 创建文档(随机文档id)
    post localhost:9200/索引名称/类型名称/文档id/_update 修改文档
    delete localhost:9200/索引名称/类型名称/文档id 删除文档
    get localhost:9200/索引名称/类型名称/文档id 查询文档通过id
    post localhost:9200/索引名称/类型名称/_search 查询所有数据

    基础测试

    1、创建索引

    数据添加成功,我们在创建的时候没有标明数据字段的类型,es会自动帮我们设置

    我这也可以自己设置索引的数据类型,在创建的时候。

    2、删除索引

    3、修改索引数据

    • 通过put方式在原有的数据上直接修改,把原来的数据覆盖掉(如果有些字段没写,就会变为了空)

    • 通过post的put方式指定文档id/_update修改数据(推荐使用这种方式,灵活性更高)

    4、查询索引数据

    get 索引名
    

    4、文档的花式查询

    1、简单的查询

    这里需要注意

    复杂查询

    过滤查询结果 相当于mysql种的select * 跟select 字段的区别

    排序

    分页查询

    bool 布尔值查询

    多条件查询 must就相当于sql中的and,所有条件都必须满足

    should 相当于or,只要满足了其中一个条件的就可以

    must_not 相当于not,非,不满足

    filter 过滤器

    匹配多个条件查询

    term 精确查询

    term查询是直接通过倒排索引指定的词条进程精确的查找的。

    在使用term精确查询时,类型为keyword的不会被分词器解析。

    多条件精确查询

    highlight 高亮

    5、Spingboot集成

    1、导入依赖

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

    注意点:导入的依赖版本一定要跟自己安装的版本所对应

    2、编写配置文件

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

    3测试

    3.1、创建索引

       @Autowired
        @Qualifier("restHighLevelClient")
        private RestHighLevelClient client;
    
        //测试创建索引请求 相当于一个put请求
        @Test
        void contextLoads() throws IOException {
            //创建索引请求
            CreateIndexRequest request = new CreateIndexRequest("xiaopang_index");
            //客户端执行请求
            CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
            System.out.println(response);
    
        }
    

    3.2、查询索引是否存在

    //测试查询索引
     @Test
     void contextLoads2() throws IOException {
         //查询索引请求
         GetIndexRequest request = new GetIndexRequest("xiaopang_index");
         //客户端执行请求
         boolean response = client.indices().exists(request,RequestOptions.DEFAULT);
         System.out.println(response);
    
     }
    //结果返回true
    

    3.3、删除索引

    //测试删除索引
    @Test
    void contextLoads3() throws IOException {
        //删除索引请求
        DeleteIndexRequest request = new DeleteIndexRequest("xiaopang_index");
        //客户端执行请求
        AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
        System.out.println(delete.isAcknowledged());
    
    }
    //结果返回true
    

    6、springboot集成之文档型操作

    1、添加文档

     //测试添加文档
        @Test
        public void addDocumentTest() throws IOException {
            //创建对象
            User user = new User("小胖", 13);
            //创建请求
            IndexRequest request = new IndexRequest("xiaopang");
            //创建规则 相当于 put  /xiaopang/_doc/1
            //设置文档id
            request.id("1");
            //设置请求实践
            request.timeout("1s");
            //将我们的user类封装成json,放入请求中
            request.source(JSON.toJSONString(user), XContentType.JSON);
    
            //客户端发送请求,返回响应结果
            IndexResponse index = client.index(request, RequestOptions.DEFAULT);
            System.out.println(index.toString());
            System.out.println(index.status());
    
        }
    //返回结果
    IndexResponse[index=xiaopang,type=_doc,id=1,version=1,result=created,seqNo=0,primaryTerm=1,shards={"total":2,"successful":1,"failed":0}]  //具体的信息
    CREATED  //执行的状态  添加
    

    2、查询文档信息

    //测试查询文档信息
    @Test
    public void selectDocumentTest() throws IOException {
        //创建查询请求
        GetRequest request = new GetRequest("xiaopang", "1");
    
        //判断文档是否存在
        boolean exists = client.exists(request, RequestOptions.DEFAULT);
        System.out.println(exists);
        GetResponse response = client.get(request, RequestOptions.DEFAULT);
        System.out.println(response.getSource()); //获取文档内容信息
        System.out.println(response);  //获取文档全部信息
    
    }
    //返回结果
    true
    {name=小胖, age=13}
    {"_index":"xiaopang","_type":"_doc","_id":"1","_version":1,"_seq_no":0,"_primary_term":1,"found":true,"_source":{"age":13,"name":"小胖"}}
    
    

    3、修改文档信息

     //测试修改文档信息
        @Test
        public void updateDocumentTest() throws IOException {
            //创建修改请求
            UpdateRequest request = new UpdateRequest("xiaopang", "1");
            //设置响应时间
            request.timeout("1s");
            //创建新的user类,这里相当于使用了put命令去修改文档信息,直接覆盖信息
            User user = new User("张锦豪", 18);
            //将新的user放入请求
           request.doc(JSON.toJSONString(user),XContentType.JSON);
           //客户端执行请求
            UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
            System.out.println(update.status());
        }
    //返回结果
    OK
    

    4、删除文档信息

    //测试删除文档信息
    @Test
    public void deleteDocumentTest() throws IOException {
        DeleteRequest request = new DeleteRequest("xiaopang", "1");
        request.timeout("1s");
        DeleteResponse delete = client.delete(request, RequestOptions.DEFAULT);
        System.out.println(delete.status());
    }
    //返回结果
    ok
    

    5、数据批量插入

    //数据批量插入
        @Test
        public void test1() throws IOException {
            BulkRequest bulkRequest = new BulkRequest();
            bulkRequest.timeout("10s");
            ArrayList<User> users = new ArrayList<>();
            users.add(new User("xiaopang1",1));
            users.add(new User("xiaopang2",1));
            users.add(new User("xiaopang3",1));
            users.add(new User("jinhao1",3));
            users.add(new User("jinhao2",3));
            users.add(new User("jinhao3",3));
    
            for (int i = 0; i <users.size() ; i++) {
                bulkRequest.add(
                        new IndexRequest("xiaopang")
                        .id(""+(i+1))
                        .source(JSON.toJSONString(users.get(i)),XContentType.JSON)
                );
            }
            BulkResponse responses = client.bulk(bulkRequest, RequestOptions.DEFAULT);
            System.out.println(responses.hasFailures());//是否失败,false代表成功了
        }
    

    6、复杂查询处理

      @Test
        public void test() throws IOException {
            SearchRequest request = new SearchRequest("xiaopang");
            //构建条件搜索
            SearchSourceBuilder builder = new SearchSourceBuilder();
            TermQueryBuilder matchQuery = QueryBuilders.termQuery("name", "jinhao1");
            builder.query(matchQuery);
            request.source(builder);
            builder.timeout(new TimeValue(60, TimeUnit.SECONDS));
            SearchResponse search = client.search(request, RequestOptions.DEFAULT);
            System.out.println(JSON.toJSONString(search));
            System.out.println("============================================");
            for (SearchHit hit : search.getHits().getHits()) {
                System.out.println(hit.getSourceAsMap());
            }
    
        }
    

  • 相关阅读:
    软件工程之美8讲——怎样平衡软件质量与时间成本范围的关系?
    软件工程之美7讲——大厂都在用哪些敏捷方法?(下)
    软件工程之美6讲——大厂都在用哪些敏捷方法?(上)
    C++问题少年系列
    有点捞的算法笔记
    UnityEditor简单介绍及案例
    数据可视化之图表用法(参考Antv整理)
    【思维导图】携程平台化常态化数据治理之路
    李宏毅2021机器学习/深度学习视频笔记
    力扣动态规划中等题困难题+背包问题DP专题202108012
  • 原文地址:https://www.cnblogs.com/xiaopanjava/p/14194572.html
Copyright © 2011-2022 走看看