ElasticSearch(搜索服务器)-第一天

1为什么使用es

ElasticSearch 搜索服务器。简称es。

初识es 搜索时数据库的问题

2.1是什么

搜索服务器 软件

2.1.1互联网搜索

https://www.baidu.com/

在这里插入图片描述

2.1.2站内搜索

https://www.taobao.com/
在这里插入图片描述

2.2为什么

不用es,可以使用数据库。

select * from xxx 

问题出现:

问题一:效率极低:

在这里插入图片描述

SELECT * FROM goods WHERE title LIKE '%手机%';

如果使用模糊查询,左边有通配符,不会走索引,会全表扫描,性能低

问题二:不能分词

在这里插入图片描述

SELECT * FROM goods WHERE title LIKE ‘%华为手机%';

关系型数据库提供的查询,功能太弱

问题三:数据量大时,不能分库分表

单表数据量大(大于一亿),存储空间有限,分库分表需要借助在不程序实现。(mycat

初识es 倒排索引

倒排索引:将各个文档中的内容,进行分词,形成词条。然后记录词条和数据的唯一标识(id)的对应关系,形成的产物。
在这里插入图片描述

初识es 存储、查询

存储:
在这里插入图片描述

json格式

​ es自动分词

查询:
在这里插入图片描述

​ 1关键词 分词

​ 2每个分词 去倒排索引表查询

​ 3汇总,相关度评分,高的先返回

2es入门

es概念-了解

官网:https://www.elastic.co/

特点

  • ElasticSearch是一个基于Lucene的搜索服务器
  • 是一个分布式、高扩展、高实时的搜索与数据分析引擎
  • 基于RESTful web接口 http get post put delete
  • Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种 流行的企业级搜索引擎

场景

  • 搜索:海量数据的查询
  • 日志数据分析
  • 实时数据分析

与mysql对比: nosql 面试:关系型数据库和非关系型数据库

  • MySQL有事务性,而ElasticSearch没有事务性,所以你删了的数据是无法恢复的。

  • ElasticSearch没有物理外键这个特性,,如果你的数据强一致性要求比较高,还是建议慎用

  • ElasticSearch和MySql分工不同,MySQL负责存储数据,ElasticSearch负责搜索数据。

在这里插入图片描述

es安装

详见《Elasticsearch 安装.md》

运维人员:系统参数,用户,防火墙。

ELK

window 方便地改配置文件,不用起虚拟机。

http://localhost:9200/

es辅助插件安装

三选一:

1postman

2kibana elastic专门为es数据展现做的一个可视化工具 http://localhost:5601/

3head

详见《Elasticsearch 安装.md》

es核心概念 nosql

在这里插入图片描述

索引(index)

ElasticSearch存储数据的地方,可以理解成关系型数据库中的数据库概念。

映射(mapping)

mapping定义了每个字段的类型、字段所使用的分词器等。相当于关系型数据库中的表结构

文档(document)

Elasticsearch中的最小数据单元,常以json格式显示。一个document相当于关系型数据库中的一行数据

倒排索引

一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,对应一个包含它的文档id列表。

类型(type) _doc

一种type就像一类表。如用户表、角色表等。在Elasticsearch7.X默认type为_doc

- ES 5.x中一个index可以有多种type。

- ES 6.x中一个index只能有一种type。

- ES 7.x以后,将逐步移除type这个概念,现在的操作已经不再使用,默认_doc

与mysql对比

关系型数据库(比如Mysql)非关系型数据库(Elasticsearch)
数据库Database索引Index
表Table索引Index(原为Type)
数据行Row文档Document
数据列Column字段Field
约束 Schema映射Mapping

操作es restful风格

REST(Representational State Transfer),表述性状态转移,是一组架构约束条件和原则。满足这些约束条件和 原则的应用程序或设计就是RESTful。就是一种定义接口的规范。

  • 基于HTTP。

  • 可以使用XML格式定义或JSON格式定义。

  • 每一个URI代表1种资源。

  • 客户端使用GET、POST、PUT、DELETE 4个表示操作方式的动词对服务端资源进行操作:

    GET:用来获取资源

    POST:用来新建资源(也可以用于更新资源)

    PUT:用来更新资源

    DELETE:用来删除资源

在这里插入图片描述

对数据的增删改查,使用不同的http方式!

3es操作

操作es 索引 (建表) index

使用postman测试:

添加索引

PUT http://ip:端口/索引名称

查询索引

GET http://ip:端口/索引名称
GET http://ip:端口/索引名称1,索引名称2
GET http://ip:端口/_all

删除索引

DELETE http://ip:端口/索引名称

关闭索引

POST http://ip:端口/索引名称/_close

打开索引

POST http://ip:端口/索引名称/_open

操作es 映射 数据类型

11.1简单数据类型

  • 字符串

    text:会分词,不支持聚合

    select color,count(1) from pruduct group by color. 1 藏青色 2斩男色

    keyword:不会分词,将全部内容作为一个词条,支持聚合。邮编030600,身份证号1424123112131311,特有名词:大文娱

  • 数值

    age byte

    price 12.35

    口罩 5.28*100 528

    小数——》分数 0.142857 1/7

在这里插入图片描述

  • 布尔

    boolean

  • 二进制

    binary

  • 范围类型

    integer_range, float_range, long_range, double_range, date_range

  • 日期

    date

11.2复杂数据类型

  • 数组:[ ]

  • 对象:{ }
    在这里插入图片描述

12 操作es 映射

  • 添加映射
PUT /person/_mapping
{
  "properties":{
    "name":{
      "type":"text"
    },
    "age":{
      "type":"integer"
    }
  }
}
  • 创建索引并添加映射
PUT person
{
  "mappings": {
    "properties": {
      "name":{
        "type": "text"
      },
      "age":{
        "type": "integer"
      }
    }
  }
}
  • 查询映射

    GET person/_mapping
    
  • 添加字段

PUT /person/_mapping
{
  "properties":{
    "address":{
      "type":"text"
    }
  }
}

13 操作es 文档

  • 添加文档,指定id

    PUT /person/_doc/1
    {
      "name" :"李四",
      "age" : 20,
      "address" :"太原"
    }
    
  • 添加文档,不指定id

    POST /person/_doc/
    {
      "name" :"王五",
      "age" : 20,
      "address" :"武汉"
    }
    
  • 查询指定id的文档

    GET /person/_doc/1
    
  • 修改文档

    PUT /person/_doc/1
    {
      "name" :"李四",
      "age" : 21,
      "address" :"太原"
    }
    
  • 查询所有文档

    GET /person/_search
    
  • 删除指定id文档

    DELETE /person/_doc/1
    

4IK分词器

14 分词器 介绍

1、分词器(Analyzer):将一段文本,按照一定逻辑,分析成多个词语的一种工具

2、ElasticSearch内置分词器:

  • Standard Analyzer -默认分词器,按词切分,小写处理
  • Simple Analyzer -按照非字母切分(符号被过滤),小写处理
  • Stop Analyzer -小写处理,停用词过滤(the,a,is)
  • Whitespace Analyzer -按照空格切分,不转小写
  • Keyword Analyzer -不分词,直接将输入当作输出
  • Patter Analyzer -正则表达式,默认\W+(非字符分割)
  • Language -提供了30多种常见语言的分词器

3、ElasticSearch内置分词器对中文很不友好,处理方式为:一个字一个词

测试:

GET _analyze
{
  "analyzer": "standard",
  "text": ["我爱北京天安门"]
}

15 IK分词器安装

  • IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。
  • 具有60万字/秒的高速处理能力。
  • 支持用户词典扩展定义。

具体安装步骤见《ik分词器安装.md》

16 ik分词器使用

ik_max_word

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

GET /_analyze
{
  "analyzer": "ik_max_word",
  "text": "乒乓球明年总冠军"
}

ik_smart

会做最粗粒度的拆分

GET /_analyze
{
  "analyzer": "ik_smart",
  "text": "乒乓球明年总冠军"
}

5文档操作

17 查询文档 使用IK

词条查询:term

1 词条查询不会分析查询条件,只有当词条和查询字符串完全匹配时才匹配搜索

GET /person/_search
{
  "query": {
    "term": {
      "address": {
        "value": "太原"
      }
    }
  }
}

**查不出来!**因为默认使用standard 分词器。

GET /person/_search
{
  "query": {
    "term": {
      "address": {
        "value": "太"
      }
    }
  }
}

可以查出来。但不是我们想要的效果。

2 重新创建索引

PUT /person
{
  "mappings": {
    "properties": {
      "name":{
        "type": "keyword"
      },
      "address":{
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart"
      }
    }
  }
}

插入数据

PUT /person/_doc/1
{
  "name" : "李四1",
  "age" : 22,
  "address" : "太原"
}
PUT /person/_doc/2
{
	   "name" : "李四2",
       "age" : 23,
       "address" : "西安"
}
PUT /person/_doc/3
{
  "name" :"李四3",
  "age" : 24,
  "address" :"广东"
}
PUT /person/_doc/4
{
  "name" :"李四4",
  "age" : 44,
  "address" :"北京海淀"
}

搜索

GET /person/_search
{
  "query": {
    "term": {
      "address": {
        "value": "北京"
      }
    }
  }
}

可以搜索出来。“北京海淀”查不出来。

全文查询:match

全文查询会分析查询条件,先将查询条件进行分词,然后查询,求并集。

GET /person/_search
{
  "query": {
    "match": {
      "address": "北京 昌平"
    }
  }
}

可以查出来。因为将搜索条件进行分词。

18 javaAPI

1创建spring-boot工程

2导入依赖

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

3测试类创建客户端

RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("192.168.25.129", 9200, "http")
 )
);
System.out.println(client);

4config类自动加载bean com.itheima.es11.config

public class ElasticSearchConfig {
    @Value("${elasticsearch.host}")
    private String host;
    @Value("${elasticsearch.port}")
    private int port;

    @Bean
    public RestHighLevelClient client() {
        return new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost(host, port, "http")
                )
        );
    }
}

5测试类直接引用

@Autowired
private RestHighLevelClient client;

6索引操作

19 索引的新增

测试类中添加

/**
     * 添加索引
     */
    @Test
    public void addIndex() throws IOException {
        // PUT person1

        //1创建请求
        CreateIndexRequest createIndexRequest=new CreateIndexRequest("person2");

        //2执行操作
        CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);

        //3获取结果
        boolean acknowledged = createIndexResponse.isAcknowledged();
        System.out.println("acknowledged:"+acknowledged);
        boolean shardsAcknowledged = createIndexResponse.isShardsAcknowledged();
        System.out.println("shardsAcknowledged:"+shardsAcknowledged);
        String index = createIndexResponse.index();
        System.out.println("index:"+index);

    }


    // PUT person3
    // {
    //     "mappings": {
    //       "properties": {
    //         "name":{
    //             "type": "keyword"
    //         },
    //         "address":{
    //             "type": "text",
    //             "analyzer": "ik_max_word"
    //         }
    //     }
    // }
    // }
    /**
     * 添加索引和映射
     */
    @Test
    public void addIndexAndMapping() throws IOException {
        // PUT person1

        //1创建请求
        CreateIndexRequest createIndexRequest=new CreateIndexRequest("person4");
        createIndexRequest.mapping("{\n" +
                "    \"properties\": {\n" +
                "      \"name\":{\n" +
                "        \"type\": \"keyword\"\n" +
                "      },\n" +
                "      \"address\":{\n" +
                "        \"type\": \"text\",\n" +
                "        \"analyzer\": \"ik_max_word\"\n" +
                "      }\n" +
                "    }\n" +
                "  }", XContentType.JSON);

        //2执行操作
        CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);

        //3获取结果
        boolean acknowledged = createIndexResponse.isAcknowledged();
        System.out.println("acknowledged:"+acknowledged);
        boolean shardsAcknowledged = createIndexResponse.isShardsAcknowledged();
        System.out.println("shardsAcknowledged:"+shardsAcknowledged);
        String index = createIndexResponse.index();
        System.out.println("index:"+index);

    }

20 javaApi 查询 删除 判断索引

测试类添加

   /**
     * 查询索引
     */
    @Test
    public void testGetIndex() throws IOException {
        // GET person
        //1创建请求
        GetIndexRequest getIndexRequest = new GetIndexRequest("person");

        //2执行操作
        GetIndexResponse getIndexResponse = client.indices().get(getIndexRequest, RequestOptions.DEFAULT);

        //3获取结果
        Map<String, MappingMetaData> mappings = getIndexResponse.getMappings();
        Set<String> keySet = mappings.keySet();
        for (String key : keySet) {
            System.out.println(key + ":" + mappings.get(key).getSourceAsMap());
        }
    }

    /**
     * 删除索引
     */
    @Test
    public void testDeleteIndex() throws IOException {
        // DELETE person1
        //1创建请求
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("person2");

        //2执行操作
        AcknowledgedResponse delete = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);

        //3获取结果
        boolean acknowledged = delete.isAcknowledged();
        System.out.println(acknowledged);

    }

    /**
     * 判断索引
     */
    @Test
    public void testExistIndex() throws IOException {
        // GET person3
        //1创建请求
        GetIndexRequest getIndexRequest = new GetIndexRequest("person3");
        //2执行操作
        boolean exists = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT);

        //3获取结果
        System.out.println(exists);
    }

关闭索引

打开索引

21 javaApi 新增文档

测试类添加

    /**
     * 添加文档
     */
    @Test
    public void testAddDoc() throws IOException {
        // PUT /person3/_doc/1
        // {
        //     "name" :"李四4",
        //      "age" : 44,
        //      "address" :"北京海淀"
        // }
        //1创建请求
        IndexRequest indexRequest = new IndexRequest("person3").type("_doc").id("2");

        Map<String, Object> sourceMap = new HashMap<>();
        sourceMap.put("name", "李四4");
        sourceMap.put("age", 44);
        sourceMap.put("address", "北京海淀");

        indexRequest.source(sourceMap);

        //2执行操作
        IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);

        //3获取结果
        String id = indexResponse.getId();
        System.out.println(id);
        DocWriteResponse.Result result = indexResponse.getResult();
        System.out.println(result);
    }


    /**
     * 添加文档,对象做参数
     */
   @Test
    public void testAddDoc() throws IOException {
        //1创建请求
        // POST /person7/_doc/1
        // {
        //     "name":"zhangsan",
        //     "address":"太原"
        // }
        // IndexRequest indexRequest=new IndexRequest("person7","_doc","2");
        IndexRequest indexRequest=new IndexRequest("person7");
        indexRequest.id("2");

        //方式一
        // HashMap<String, String> map = new HashMap<>();
        // map.put("name","zhangsan");
        // map.put("address","太原");
        // indexRequest.source(map);

        //方式二
        // XContentBuilder builder = XContentFactory.jsonBuilder();
        // builder.startObject();
        // {
        //     builder.field("name","zhangsan");
        //     builder.field("address","太原");
        // }
        // builder.endObject();
        // indexRequest.source(builder);

        //方式三
        // indexRequest.source("{\n" +
        //         "  \"name\":\"zhangsan\",\n" +
        //         "  \"address\":\"太原\"\n" +
        //         "}",XContentType.JSON);

        //方式四
        indexRequest.source("name","zhangsan"
                ,"address","太原"
                ,"age",18);

        //2执行操作
        IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);

        //3获取结果
        // {
        //         "_index" : "person7",
        //         "_type" : "_doc",
        //         "_id" : "1",
        //         "_version" : 1,
        //         "result" : "created",
        //         "_shards" : {
        //              "total" : 2,
        //             "successful" : 1,
        //             "failed" : 0
        // },
        //     "_seq_no" : 0,
        //         "_primary_term" : 1
        // }

        System.out.println(indexResponse.getId());
        System.out.println(indexResponse.getIndex());
        System.out.println(indexResponse.getVersion());
        System.out.println(indexResponse.getResult().getLowercase());

    }

22 javaApi 修改查询删除文档

测试类添加

    /**
     * 修改文档,对象做参数。就是添加文档!
     */
    @Test
    public void testUpdateDocPerson() throws IOException {
        // PUT /person3/_doc/1
        // {
        //     "name" :"李四4",
        //      "age" : 44,
        //      "address" :"北京海淀"
        // }
        Person person=new Person();
        person.setId("33");
        person.setName("zhangsan");
        person.setAge(28);
        person.setAddress("山西");

        String json = JSON.toJSONString(person);

        //1创建请求
        IndexRequest indexRequest = new IndexRequest("person3").type("_doc").id(person.getId());
        indexRequest.source(json,XContentType.JSON);



        //2执行操作
        IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);

        //3获取结果
        String id = indexResponse.getId();
        System.out.println(id);
        DocWriteResponse.Result result = indexResponse.getResult();
        System.out.println(result);
    }

    /**
     * 根据Id查询文档
     */
    @Test
    public void testFindDocById() throws IOException {
        // GET /person3/_doc/33

        //1创建请求
        GetRequest getRequest=new GetRequest("person3","33");

        //2执行操作
        GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);

        //3获取结果
        Map<String, Object> sourceAsMap = getResponse.getSourceAsMap();
        System.out.println(sourceAsMap);
    }


    /**
     * 根据Id删除文档
     */
    @Test
    public void testDeleteDocById() throws IOException {
        // Delete /person3/_doc/2

        //1创建请求
        DeleteRequest deleteRequest=new DeleteRequest("person3","2");

        //2执行操作
        DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);

        //3获取结果
        DocWriteResponse.Result result = deleteResponse.getResult();
        System.out.println(result);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值