ElasticSearch学习总结(一)

1 初识ElasticSearch

倒排索引:将文档进行分词,形成词条和id的对应关系即为反向索引。
(倒排索引:将各个文档中的内容,进行分词,形成词条,然后记录词条和数据的唯一标识(id)的对应关系,形成的产物)
以唐诗为例,所处包含“前”的诗句

正向索引:由《静夜思》–>窗前明月光—>“前”字

反向索引:“前”字–>窗前明月光–>《静夜思》

反向索引的实现就是对诗句进行分词,分成单个的词,由词推据,即为反向索引

ES存储和查询的原理

index(索引):相当于mysql的库

映射:相当于mysql 的表结构

document(文档):相当于mysql的表中的数据

数据库查询存在的问题

  1. 性能低:使用模糊查询,左边有通配符,不会走索引,会全表扫描,性能低
  2. 功能弱:如果以”华为手机“作为条件,查询不出来数据Es使用倒排索引,对title 进行分词

1.1 ES概念详解

ElasticSearch是一个基于Lucene的搜索服务器,是一个分布式、高扩展、高实时的搜索与数据分析引擎
在这里插入图片描述

ES是基于RESTful web接口实现的查询

Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎

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

1.2 应用场景

搜索:海量数据的查询

日志数据分析

实时数据分析

1.3 数据同步

如果想实现"mysql"与"elasticSearch"的数据自动同步, 可以使用开源框架"alibaba/canal".

https://github.com/alibaba/canal/

2 ES核心概念

索引(index): 对应数据库中的表

映射(mapping): 表的结构。

文档(document) : 数据库中的一行数据。

类型(type):

\- ES 5.x中一个index可以有多种type。  //那个时候,index相当于数据库,type相当于表
\- ES 6.x中一个index只能有一种type。
\- ES 7.x以后,将逐步移除type这个概念,现在的操作已经不再使用,默认_doc

3 操作ES-脚本

3.1 RESTful风格介绍

在操作ES时,需要使用使用RESTful风格的请求来操作ES。

GET:用来获取资源

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

PUT:用来更新资源

DELETE:用来删除资源

注意

ES有多种操作工具:

Postman:操作时需要指定完整路径,如添加索引使用: PUT http://ip:端口/索引名称

kibana: 操作时可以使用简化路径。如添加索引使用: PUT /索引名称

3.2 操作索引

添加索引

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 

3.3 操作映射

3.3.1 操作语法

添加映射

   PUT /索引名/_mapping
    {
        "properties":{
            "属性名":{
                "type": "属性类型",
                "analyzer": "分词类型"
            },
            "属性名":{
            	"type": "属性类型"
            }
        }
    } 

创建索引并添加映射

   PUT /索引名
    {
      "mappings": {
        "properties": {
          "属性名": {
            "type": "属性类型"
          },
          "属性名": {
            "type": "属性类型"
          }
        }
      }
    }

查询索引

GET /索引名/_mapping

添加字段

   PUT /索引名/_mapping
    {
      "properties": {
          "属性名": {
            "type": "属性类型"
          }
       }
    }
    # 添加字段指的是“在映射已经添加完成的情况,对映射增加一个字段”

3.3.2 数据类型

简单数据类型

  • 字符串
    text:会分词,不支持聚合
    keyword:不会分词,将全部内容作为一个词条,支持聚合(类似于可以执行sum之类的统计)
  • 数值
  • 布尔:boolean
  • 二进制:binary
  • 范围类型:integer_range, float_range, long_range, double_range, date_range
  • 日期:date

复杂数据类型

  • 数组:[ ] 数组类型的JSON对象
  • 对象:{ } 单个JSON对象

3.4 操作文档

添加文档,指定id

POST /索引名/_doc/id号
{
  "属性名":"属性值",
  "属性名":属性值,
  "属性名":"属性值"
}

添加文档,不指定id

   #添加文档,不指定id(系统会随机ID)
    POST /索引名/_doc/
    {
      "属性名":"属性值",
      "属性名":属性值,
      "属性名":"属性值"
    }

查询指定文档

GET /索引名/_search/指定ID

查询所有文档

GET /索引名/_search

删除指定id文档

DELETE /索引名/_doc/1

修改文档,指定id

PUT /索引名/_doc/id号
{
  "属性名":"属性值",
  "属性名":属性值,
  "属性名":"属性值"
}

4 分词器

4.1 分词器-介绍

分词器的作用是将一串字符串改为“词”的列表,主要用来建立“倒排索引”,方便后续ES查询。

如“大学生活”,可分为:[大、大学、大学生、学、学生、生、生活、活]。

IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包

IKAnalyzer是一个基于Maven构建的项目,具有60万字/秒的高速处理能力,支持用户词典扩展定义

下载地址:https://github.com/medcl/elasticsearch-analysis-ik/archive/v7.4.0.zip

4.2 ik分词器使用

IK分词器有两种分词模式:ik_max_word和ik_smart模式。

4.2.1 ik_max_word

会将文本做最细粒度的拆分,比如会将“乒乓球明年总冠军”拆分为“乒乓球、乒乓、球、明年、总冠军、冠军。

例如:

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

分词器结果:

{
  "tokens" : [
    {
      "token" : "乒乓球",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "乒乓",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "球",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "CN_CHAR",
      "position" : 2
    },
    {
      "token" : "明年",
      "start_offset" : 3,
      "end_offset" : 5,
      "type" : "CN_WORD",
      "position" : 3
    },
    {
      "token" : "总冠军",
      "start_offset" : 5,
      "end_offset" : 8,
      "type" : "CN_WORD",
      "position" : 4
    },
    {
      "token" : "冠军",
      "start_offset" : 6,
      "end_offset" : 8,
      "type" : "CN_WORD",
      "position" : 5
    }
  ]
}

4.2.2 ik_smart

会做最粗粒度的拆分,比如会将“乒乓球明年总冠军”拆分为乒乓球、明年、总冠军。

例如:

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

分词器结果:

  {
      "tokens" : [
        {
          "token" : "乒乓球",
          "start_offset" : 0,
          "end_offset" : 3,
          "type" : "CN_WORD",
          "position" : 0
        },
        {
          "token" : "明年",
          "start_offset" : 3,
          "end_offset" : 5,
          "type" : "CN_WORD",
          "position" : 1
        },
        {
          "token" : "总冠军",
          "start_offset" : 5,
          "end_offset" : 8,
          "type" : "CN_WORD",
          "position" : 2
        }
      ]
    }

4.3 使用IK分词器-查询文档

词条查询:term

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

全文查询:match

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

词条查询:term

# 查询person中,address属性包含"北京昌平"词条的数据。
# 注意:address所拆分出来的词条中,必须包含完整的“北京昌平”词条,则数据才能别查询出来
GET /person/_search
{
  "query": {
    "term": {
      "address": {
        "value": "北京昌平"
      }
    }
  }
}

全文查询:match

   #IK会先把“北京昌平”进行词条拆分,比如拆为“北京”,“昌平”。
    #然后分别查询“北京”,“昌平”,然后求并集
    GET /person/_search
    {
      "query": {
        "match": {
          "address":"北京昌平"
        }
      }
    }

5 操作ES-JavaAPI

5.1 SpringBoot整合ES

①搭建SpringBoot工程

②引入ElasticSearch相关坐标

   <!--引入es的坐标-->
    <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>

配置端口信息

spring.elasticsearch.rest.uris=http://192.168.111.132:9200

③ 创建ES实体类

@Document(indexName = "user")  //索引的名
public class User {
    @Id
    @Field(type = FieldType.Integer)
    private Integer id;
    @Field(type = FieldType.Keyword)
    private String name;
    @Field(type = FieldType.Integer)
    private Integer age;
    @Field(type = FieldType.Text ,analyzer = "ik_smart")
    private String address;

5.2.3 索引,操作

@SpringBootTest
class EsIndexTests{

    @Autowired
    private ElasticsearchRestTemplate restTemplate;

    /**
     * 添加索引
     */
    @Test
    public  void  addIndexTest(){
        boolean b = restTemplate.indexOps(User.class).create();
        System.out.println(b);
    }

    /**
     * 删除索引
     */
    @Test
    public  void deleteIndexTest(){
        boolean delete = restTemplate.indexOps(User.class).delete();
        System.out.println(delete);
    }

}

5.3 映射操作

@SpringBootTest
public class EsMappingTest {

    @Autowired
    private ElasticsearchRestTemplate restTemplate;

    /**
     * 添加映射
     */
    @Test
  public  void addMappingTest(){
        boolean exists = restTemplate.indexOps(User.class).exists();  //判断是否存在索引
        if (!exists){ //若不存在,则创建索引
          restTemplate.indexOps(User.class).create();
        }
        boolean mapping = restTemplate.indexOps(User.class).putMapping(User.class); //创建映射
        System.out.println(mapping);
    }

    /**
     * 查询映射
     */
    @Test
    public  void findMappingTest(){
        Map<String, Object> mapping = restTemplate.indexOps(User.class).getMapping();
        System.out.println(mapping);
    }
}

5.4 文档操作

@SpringBootTest
public class EsDocumentTest {
    @Autowired //映射注入
    private ElasticsearchRestTemplate restTemplate;

    /**
     * 添加文档信息
     * 若修改,则id 相同,内容不同即可进行内容的覆盖
     */
    @Test
    public void addDocumentTest() {
        User user1 = new User(1, "石破天", 23, "侠客岛");
        User user2 = new User(2, "郭靖", 23, "襄阳");
        User user3 = new User(3, "虚竹", 23, "飘渺峰");
        User[] us = {user1, user2, user3};
        Iterable<User> users = restTemplate.save(us);
        Iterator<User> iterator = users.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }

    /**
     * 根据id修改信息
     * 若修改,则id 相同,内容不同即可进行内容的覆盖
     */

    @Test
    public void updateDocumentTest() {
        User user = new User(1, "石破天2.0", 23, "侠客岛2.0");
        restTemplate.save(user);
    }

    /**
     * 查询
     */
    @Test
    public void findDocumentTest() {
        User user = restTemplate.get("1", User.class);
        System.out.println(user);
    }

    /**
     * 根据id删除文档信息
     */
    @Test
    public void deleteDocumentTest() {
        String delete = restTemplate.delete("1", User.class);
        System.out.println(delete);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大梦谁先觉i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值