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());
        }

    }

原文地址:https://www.cnblogs.com/xiaopanjava/p/14194572.html