Elasticsearch入门教程

简介

本文只介绍一些与Elasticsearch使用相关的方法和概念,不涉及部署和运维方面的知识。只求能让学习过关系型数据库的同学快速入门Elasticsearch。所有内容基于es 7.x。

Elasticsearch与mysql的区别是什么?

区别 elasticsearch mysql
调用方式 使用restful api的方式调用 使用sql的的方式调用
索引方式 倒排索引 B+ 树
部署方式 天生支持集群部署,可横向扩展 不支持

Elasticsearch使用场景是什么?

  • 需要做全文搜索(如:商品搜索、日志消息)
  • 商业智能、数据分析

Elasticsearch生态有哪些组件?

Elasticsearch数据库是由一个商业公司开发,该公司为Elasticsearch配备了一系列周边工具。目的是为了增加Elasticsearch数据库使用场景,让Elasticsearch更加容易上手。

  • Kibana

相当于Elasticsearch的控制台。在这里你可以执行增删改拆语句、查看整个Elasticsearch的集群运行状态、将数据可视化,甚至这里集合了很多小工具。比如:链路追踪、监控服务可用性等等。但是Kibana只负责这些小工具的数据展示功能。具体的收集信息和储存信息是其他组件做的事情。

  • Logstash

采集数据的工具,运输数据的过程中支持过滤和转化。他的输入输出端不仅仅能够对接Elasticsearch而且可以对接其他数据源。输入和输出都是插件化的,所以你也可以针对你想要的数据源进行开发。

  • Beats

采集数据的工具,支持多种类型的采集形式。比如文件、性能指标、心跳等等。它也可以对接不同的输入输出源

那么LogstashBeats的区别是什么呢?

首先他们都能做采集和输出。不过他们的侧重点不同。Beats才有go编写、Logstash是由java编写。这就导致Beats更加轻量级,采集的时候对宿主机的影响最小。
所以一般的架构是这样的。由beats到客户端本地采集,然后将数据发布给中间件(kafka),接下来由logstash解析、转化、过滤kafka中的消息,最终以统一的形式保存到elasticsarch。

Elasticsearch为什么支持全文搜索?

倒排索引是支持全文搜索的核心算法。具体原理看这里:https://www.cnblogs.com/cjsblog/p/10327673.html

一些概念

索引(index)

相当于关系型数据库中的table。所有结构一样的数据都放到同一个index中。

文档(document)

相当于关系数据库中的一条记录。不过这里存的是json格式。

数据类型

在创建index的时候可以指定数据类型,以及这个index的一些其他属性。
参考文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html

String字段被拆分成两种新的数据类型

  • text:会自动分词,然后被索引,不支持聚合
  • keyword:不进行分词,直接索引,支持聚合

增删改

新建index

1
2
3
4
5
6
7
8
9
10
PUT /index_name
{
"mappings": {
"properties": {
"age": { "type": "integer" },
"email": { "type": "keyword" },
"name": { "type": "text" }
}
}
}

对于index的结构的增删改可以参考新建index

新增document

新增一个id为1的文档。对同一个id多次调用put方法,会完整的覆盖掉之前的文档。详细用法参考这里

1
2
3
4
5
6
PUT /test/_doc/1
{
"name": "zhangsan",
"email": "1@qq.com",
"age": 18
}

修改document

详细参考按id修改按条件修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//只更新name字段
POST /test/_update/1
{
"doc":{
"name": "fd"
}
}

//根据自定义条件修改:age加1。如果使用自定义条件修改,那么就只能使用script去写脚本修改数据。
POST /test/_update_by_query
{
"script": {
"source": "ctx._source.age++;ctx._source.name='yyh'",
"lang": "painless"
},
"query": {
"term": {
"name": "fd"
}
}
}

删除document

1
DELETE /test/_doc/1

删除index

1
DELETE /test

搜索

计数

1
2
GET /index_name/_count
{}

根据主键获取数据

1
GET /index_name/_doc/主键值

查看表结构

1
GET /index_name/_mapping

分页和排序

  • 分页,from:从第几条记录开始,size:获取多少条数据。
  • 排序,sort中填写要排序的字段
1
2
3
4
5
6
7
8
9
10
11
12
GET /jte_pms_business-t_pms_history_order/_search
{
"from": 0,
"size" : 10,
"sort": [
{
"create_time": {
"order": "desc"
}
}
]
}

查询(query)与过滤(filter)

  • query会询问每个文档的字段值与特定值的匹配程度如何。
  • filter会询问每个文档的字段值是否包含着特定值。
  • 原则上来说,使用查询(query)语句再需要进行相关性评分的时候使用,其他情况的全部用过滤(filter)语句。
  • 查询(query)与过滤(filter)可以混合一起使用。但是filter不参与结果相关性的打分。参考这里
  • 使用filter时,filter必须放到query和bool节点下。
1
2
3
4
5
6
7
8
9
10
11
12
13
//单独使用filter查询
GET /jte_pms_business-t_pms_history_order/_search
{
"query": {
"bool": {
"filter": [
{"term": {
"order_code": "ZQ1ZZ210514002"
}}
]
}
}
}

混合查询

boolean查询

bool 过滤可以用来合并多个过滤条件查询结果的布尔逻辑,它包含一下操作符:

  • must: 多个查询条件的完全匹配,相当于 and。
  • must_not: 多个查询条件的相反匹配,相当于 not。
  • should: 至少有一个查询条件匹配, 相当于 or。
  • filter: 结果必须匹配这个条件。此条件在过滤(filter)环境下运行,不影响结果得分。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    POST _search
    {
    "query": {
    "bool" : {
    "must" : {
    "term" : { "user" : "kimchy" }
    },
    "filter": {
    "term" : { "tag" : "tech" }
    },
    "must_not" : {
    "range" : {
    "age" : { "gte" : 10, "lte" : 20 }
    }
    },
    "should" : [
    { "term" : { "tag" : "wow" } },
    { "term" : { "tag" : "elasticsearch" } }
    ]
    }
    }
    }

    全文搜索

    match

  • 它是一个高级全文查询 ,这表示它既能处理全文字段,又能处理精确字段。
  • 它能匹配到与搜索条件不全等的字符串。比如搜索“I love china”,那么“I don’t love china”这个字符串可以匹配到,只是得分较低。
  • 参考链接
    1
    2
    3
    4
    5
    6
    7
    8
    GET /my_index/my_type/_search
    {
    "query": {
    "match": {
    "title": "QUICK!"
    }
    }
    }

    match_phrase

  • 类似 match 查询, match_phrase查询首先将查询字符串解析成一个词项列表,然后对这些词项进行搜索,但只保留那些包含全部搜索词项,且位置与搜索词项相同的文档。
  • 他只能搜索到和条件全等的字符串。比如搜索“I love china”,那么“I don’t love china”这个字符串不会匹配到。
  • 参考链接

    match_phrase_prefix

  • match_phrase的一种特殊形式,相当于前缀查询。
  • 比较耗费性能,需要搭配max_expansions使用。用于限定最多查出多少个结果。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    GET /_search
    {
    "query": {
    "match_phrase_prefix" : {
    "message" : {
    "query" : "quick brown f"
    }
    }
    }
    }

    multi_match

  • 基于match同时搜索一个index中的多个属性
  • fields支持模糊匹配
  • 有很多匹配策略,详情参考这里
    1
    2
    3
    4
    5
    6
    7
    8
    9
    GET /_search
    {
    "query": {
    "multi_match" : {
    "query": "this is a test",
    "fields": [ "subject", "message" ]
    }
    }
    }

Term级别的查询

你可以使用Term级别的查询来搜索精确的值。不像全文搜索,它不使用分词器。他直接去精确匹配字面值。所以一般应用在keyword数据类型上,而不是text数据类型上。

  • range 查询找出那些落在指定区间内的数字或者时间:
  • term 查询被用于精确值匹配,这些精确值可能是数字、时间、布尔或者那些 not_analyzed 的字符串
  • terms 查询和 term 查询一样,但它允许你指定多值进行匹配。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件
  • 更多查询方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    GET /_search
    {
    "query": {
    "term": {
    "user": {
    "value": "Kimchy"
    }
    }
    }
    }

    分词器

    安装

  • 到这里下载与es对应版本的zip压缩包
  • 然后解压到“es安装目录/plugins/ik”。
  • 重启es
  • 启动日志中会包含ik的加载日志

    使用

    ik分词器分为2种类型:

  • ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”,会穷尽各种可能的组合,适合 Term Query;
  • ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”,适合 Phrase 查询。

    Es中如何定义分词器

    分词器可定义到analyzer和search_analyzer上。
  • analyzer是当插入新文档时使用,将text类型的字段做分词然后插入倒排索引。
  • search_analyzer是查询时被使用,分词器将查询条件解析成多个短语从倒排索引中查询数据
  • 创建使用ik作为分词器的索引
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    curl -XPOST http://localhost:9200/index/_mapping -H 'Content-Type:application/json' -d'
    {
    "properties": {
    "content": {
    "type": "text",
    "analyzer": "ik_max_word",
    "search_analyzer": "ik_smart"
    }
    }

    }'
  • 分词测试
    1
    2
    3
    4
    5
    POST /index/_analyze?pretty=true
    {
    "text": "中国一定能称霸世界",
    "tokenizer":"ik_smart"
    }

原文链接:https://www.jdkdownload.com/es_tutorial.html