ElasticSearch 之初步上手

1. Elasticsearch 产生背景

1.1 大规模数据如何检索
如:当系统数据量上了10亿、100亿条的时候,在做系统架构的时候通常会从以下角度去考虑问题:

1)用什么数据库好?(mysql、oracle、mongodb、hbase…)
2)如何解决单点故障;(lvs、F5、A10、Zookeeper、MQ)
3)如何保证数据安全性;(热备、冷备、异地多活)
4)如何解决检索难题;(数据库代理中间件:mysql-proxy、Cobar、MaxScale等;)
5)如何解决统计分析问题;(离线、近实时)

1.2 传统数据库的应对解决方案
对于关系型数据,我们通常采用以下或类似架构去解决查询瓶颈和写入瓶颈:
解决要点:

1)通过主从备份解决数据安全性问题;
2)通过数据库代理中间件心跳监测,解决单点故障问题;
3)通过代理中间件将查询语句分发到各个slave节点进行查询,并汇总结果

1.3 非关系型数据库解决方案
对于Nosql数据库,以mongodb为例,其它原理类似:
解决要点:

1)通过副本备份保证数据安全性;
2)通过节点竞选机制解决单点问题;
3)先从配置库检索分片信息,然后将请求分发到各个节点,最后由路由节点合并汇总结果

1.4 内存数据库解决方案
完全把数据放在内存中是不可靠的,实际上也不太现实,当我们的数据达到PB级别时,按照每个节点96G内存计算,在内存完全装满的数据情况下,需要的机器是:1PB=1024T=1048576G
节点数=1048576/96=10922个
实际上,考虑到数据备份,节点数往往在2.5万台左右。成本巨大决定了其不现实!

所以把数据放在内存也好,不放在内存也好,都不能完完全全解决问题。
全部放在内存速度问题是解决了,但成本问题上来了。
为解决以上问题,从源头着手分析,通常会从以下方式来寻找方法:

1、存储数据时按有序存储;
2、将数据和索引分离;
3、压缩数据;

这就引出了 Elasticsearch

2. Elasticsearch 介绍

Elasticsearch 是一个基于Lucene的分布式搜索和分析引擎。

ES是elaticsearch简写, Elasticsearch是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。
Elasticsearch使用Java开发,在Apache许可条款下开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便

使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,使得全文检索变得简单

设计用途:用于分布式全文检索,通过HTTP使用JSON进行数据索引,速度快

2.1 Lucene与Elasticsearch关系

1)Lucene只是一个库。想要使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。

2)Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。

2.2 Elasticsearch核心概念

Cluster:集群
ES可以作为一个独立的单个搜索服务器。不过,为了处理大型数据集,实现容错和高可用性,ES可以运行在许多互相合作的服务器上。这些服务器的集合称为集群。

Node:节点
形成集群的每个服务器称为节点。

Shard:分片
当有大量的文档时,由于内存的限制、磁盘处理能力不足、无法足够快的响应客户端的请求等,一个节点可能不够。这种情况下,数据可以分为较小的分片。每个分片放到不同的服务器上。
当你查询的索引分布在多个分片上时,ES会把查询发送给每个相关的分片,并将结果组合在一起,而应用程序并不知道分片的存在。即:这个过程对用户来说是透明的。

Replia:副本
为提高查询吞吐量或实现高可用性,可以使用分片副本。
副本是一个分片的精确复制,每个分片可以有零个或多个副本。ES中可以有许多相同的分片,其中之一被选择更改索引操作,这种特殊的分片称为主分片。
当主分片丢失时,如:该分片所在的数据不可用时,集群将副本提升为新的主分片。

全文检索
全文检索就是对一篇文章进行索引,可以根据关键字搜索,类似于mysql里的like语句。
全文索引就是把内容根据词的意义进行分词,然后分别创建索引,例如”今日是周日我们出去玩” 可能会被分词成:“今天“,”周日“,“我们“,”出去玩“ 等token,这样当你搜索“周日” 或者 “出去玩” 都会把这句搜出来。

2.3 与关系型数据库Mysql对比

在这里插入图片描述

  1. 关系型数据库中的数据库(DataBase),等价于ES中的索引(Index)
  2. 一个数据库下面有N张表(Table),等价于1个索引Index下面有N多类型(Type),
  3. 一个数据库表(Table)下的数据由多行(ROW)多列(column,属性)组成,等价于1个Type由多个文档(Document)和多Field组成。
  4. 在一个关系型数据库里面,schema定义了表、每个表的字段,还有表和字段之间的关系。 与之对应的,在ES中:Mapping定义索引下的Type的字段处理规则,即索引如何建立、索引类型、是否保存原始索引JSON文档、是否压缩原始JSON文档、是否需要分词处理、如何进行分词处理等。
  5. 在数据库中的增insert、删delete、改update、查search操作等价于ES中的增PUT/POST、删Delete、改_update、查GET.1.7

2.4 ES逻辑设计(文档–>类型–>索引)

一个索引类型中,包含多个文档,比如说文档1,文档2。
当我们索引一篇文档时,可以通过这样的顺序找到它:索引 ▷ 类型 ▷文档ID,通过这个组合我们就能索引到某个具体的文档。
注意:ID不必是整数,实际上它是个字符串。

文档
之前说elasticsearch是面向文档的,那么就意味着索引和搜索数据的最小单位是文档,elasticsearch中,文档有几个重要属性:

  • 自我包含,一篇文档同时包含字段和对应的值,也就是同时包含key:value
  • 可以是层次型的,一个文档中包含自文档,复杂的逻辑实体就是这么来的
  • 灵活的结构,文档不依赖预先定义的模式,我们知道关系型数据库中,要提前定义字段才能使用,在elasticsearch中,对于字段是非常灵活的,有时候,我们可以忽略该字段,或者动态的添加一个新的字段。
  • 文档是无模式的,也就是说,字段对应值的类型可以是不限类型的。

尽管我们可以随意的新增或者忽略某个字段,但是,每个字段的类型非常重要,比如一个年龄字段类型,可以是字符串也可以是整型。因为elasticsearch会保存字段和类型之间的映射及其他的设置。这种映射具体到每个映射的每种类型(详见扩展阅读:17-扩展阅读-删除映射类型.md),这也是为什么在elasticsearch中,类型有时候也称为映射类型。

类型
1、类型是文档的逻辑容器,就像关系型数据库一样,表格是行的容器。
2、类型中对于字段的定义称为映射,比如name映射为字符串类型。
3、我们说文档是无模式的,它们不需要拥有映射中所定义的所有字段,比如新增一个字段,是怎么做的呢?elasticsearch会自动的将新字段加入映射,但是这个字段的不确定它是什么类型,elasticsearch就开始猜,如果这个值是18,那么elasticsearch会认为它是整型。
4、但是elasticsearch也可能猜不对,所以最安全的方式就是提前定义好所需要的映射,这点跟关系型数据库殊途同归了,先定义好字段,然后再使用,别整什么幺蛾子。后面在讨论更多关于映射的东西。

索引
索引是映射类型的容器,elasticsearch中的索引是一个非常大的文档集合。索引存储了映射类型的字段和其他设置。然后它们被存储到了各个分片上了。

2.5 ES物理设计

一个集群包含至少一个节点,而一个节点就是一个elasticsearch进程。节点内可以有多个索引。
默认的,如果你创建一个索引,那么这个索引将会有5个分片(primary shard,又称主分片)构成,而每个分片又有一个副本(replica shard,又称复制分片),这样,就有了10个分片。
那么这个索引是如何存储在集群中的呢?
图中有3个节点的集群,可以看到主分片和对应的复制分片都不会在同一个节点内,这样有利于某个节点挂掉了,数据也不至于丢失。
实际上,一个分片是一个Lucene索引,一个包含倒排索引的文件目录,倒排索引的结构使得elasticsearch在不扫描全部文档的情况下,就能告诉你哪些文档包含特定的关键字

在这里插入图片描述

2.6 ELK是什么

ELK=elasticsearch+Logstash+kibana
elasticsearch:后台分布式存储以及全文检索
logstash: 日志加工、“搬运工”
kibana:数据可视化展示。
ELK架构为数据分布式存储、可视化查询和日志解析创建了一个功能强大的管理链。 三者相互配合,取长补短,共同完成分布式大数据处理工作。

2.7 Elasticsearch特点和优势

1)分布式实时文件存储,可将每一个字段存入索引,使其可以被检索到。
2)实时分析的分布式搜索引擎。
分布式:索引分拆成多个分片,每个分片可有零个或多个副本。集群中的每个数据节点都可承载一个或多个分片,并且协调和处理各种操作;
负载再平衡和路由在大多数情况下自动完成。
3)可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据。也可以运行在单台PC上(已测试)
4)支持插件机制,分词插件、同步插件、Hadoop插件、可视化插件等。

2.8 Elasticsearch 业务场景

实际项目开发实战中,几乎每个系统都会有一个搜索的功能,当搜索做到一定程度时,维护和扩展起来难度就会慢慢变大,所以很多公司都会把搜索单独独立出一个模块,用ElasticSearch等来实现。

近年ElasticSearch发展迅猛,已经超越了其最初的纯搜索引擎的角色,现在已经增加了数据聚合分析(aggregation)和可视化的特性,如果你有数百万的文档需要通过关键词进行定位时,ElasticSearch肯定是最佳选择。当然,如果你的文档是JSON的,你也可以把ElasticSearch当作一种“NoSQL数据库”, 应用ElasticSearch数据聚合分析(aggregation)的特性,针对数据进行多维度的分析。

尝试使用ES来替代传统的NoSQL,它的横向扩展机制太方便了

应用场景:

1)新系统开发尝试使用ES作为存储和检索服务器;
2)现有系统升级需要支持全文检索服务,需要使用ES

2.9 Elasticsearch 索引到底能处理多大数据

单一索引的极限取决于存储索引的硬件、索引的设计、如何处理数据以及你为索引备份了多少副本。

通常来说,一个Lucene索引(也就是一个elasticsearch分片,一个es索引默认5个分片)不能处理多于21亿篇文档,或者多于2740亿的唯一词条。但达到这个极限之前,我们可能就没有足够的磁盘空间了!
当然,一个分片如何很大的话,读写性能将会变得非常差

3. ElasticSearch 安装

3.1 安装 ElasticSearch

一、 安装JDK环境
因为ElasticSearch是用Java语言编写的,所以必须安装JDK的环境,并且是JDK 1.8以上
官方网址:https://www.oracle.com/java/technologies/downloads/

安装完成查看java版本

java -version

在这里插入图片描述

二、 官网下载elasticsearch

官方网站:https://www.elastic.co/cn/downloads/elasticsearch

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
三、 启动 es

1. 下载完成后解压并在cmd中切换到bin路径下
   cd elasticsearch-<version>/bin
   
2. 启动es,在 cmd 中输入 elasticsearch 启动。如果是在 Windows 上面运行 Elasticseach,应该
   运行 bin/elasticsearch.bat 而不是 bin/elasticsearch

启动完可以测试,如下所示:

在浏览器输入以下地址:http://127.0.0.1:9200/,可以看到以下内容
在这里插入图片描述

如果在运行中出现如下异常

在这里插入图片描述

只需要将 elasticsearch-7.5.0\config\elasticsearch.keystore.tmp 文件删除即可

3.2 关闭 es

# 查看进程
ps -ef | grep elastic

# 干掉进程
kill -9 2382(进程号)

# 以守护进程方式启动es
elasticsearch -d

4. Elasticsearch 插件介绍

es插件是一种增强Elasticsearch核心功能的途径。它们可以为es添加自定义映射类型、自定义分词器、原生脚本、自伸缩等等扩展功能。

es插件包含JAR文件,也可能包含脚本和配置文件,并且必须在集群中的每个节点上安装。安装之后,需要重启集群中的每个节点才能使插件生效。
es插件包含核心插件和第三方插件两种

4.1 核心插件

核心插件是elasticsearch项目提供的官方插件,都是开源项目。这些插件会跟着elasticsearch版本升级进行升级,总能匹配到对应版本的elasticsearch,这些插件是有官方团队和社区成员共同开发的。

官方插件地址: https://github.com/elastic/elasticsearch/tree/master/plugins

4.2 第三方插件

第三方插件是有开发者或者第三方组织自主开发便于扩展elasticsearch功能,它们拥有自己的许可协议,在使用它们之前需要清除插件的使用协议,不一定随着elasticsearch版本升级, 所以使用者自行辨别插件和es的兼容性。

4.3 插件安装

elasticsearch的插件安装方式还是很方便易用的。

它包含了命令行,url,离线安装三种方式。
核心插件随便选择一种方式安装均可,第三方插件建议使用离线安装方式

第一种:命令行

bin/elasticsearch-plugin install [plugin_name]
# bin/elasticsearch-plugin install analysis-smartcn  安装中文分词器

第二种:url安装

bin/elasticsearch-plugin install [url]
# bin/elasticsearch-plugin install https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-smartcn/analysis-smartcn-6.4.0.zip

第三种:离线安装

#https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-smartcn/analysis-smartcn-6.4.0.zip
# 点击下载analysis-smartcn离线包
# 将离线包解压到ElasticSearch 安装目录下的 plugins 目录下
# 重启es。新装插件必须要重启es

注意:插件的版本要与 ElasticSearch 版本要一致

5. ElasticSearch 之 ElasticSearch-head

elasticsearch-head 是 elasticsearch 的一款可视化工具,依赖于 node.js ,所以需要先安装 node.js

5.1 安装 Node.js

5.2 安装 Grunt

# Grunt是基于Node.js的项目构建工具。它可以自动运行你所设定的任务 
npm install grunt -g

5.3 下载 Head

官网:https://github.com/mobz/elasticsearch-head

# 解压后切换到目录下
cd elasticsearch-head

# 通过npm安装依赖
npm install

# 启动
npm run start

# 在浏览器里打开,界面如下所示
http://localhost:9100/

在这里插入图片描述

5.4 配置跨域

修改 Elasticsearch 安装目录中 config 文件夹下 elasticsearch.yml 文件,加入下面两行:

添加配置时,:后必须空格,不然启动闪退

http.cors.enabled: true
http.cors.allow-origin: "*"

启动 Elasticsearch ,如下页面即为成功

在这里插入图片描述

6. ElasticSearch 安装 Kibana

6.1 Kibana 介绍

Kibana 是一款开源的数据分析和可视化平台,它是 Elastic Stack 成员之一,设计用于和 Elasticsearch 协作。

您、可以使用 Kibana 对 Elasticsearch 索引中的数据进行搜索、查看、交互操作。
可以很方便的利用图表、表格及地图对数据进行多元化的分析和呈现

详情可见用户手册:
https://www.elastic.co/guide/cn/kibana/current/index.html

注意跟Elasticsearch版本兼容情况,详情见:
https://www.elastic.co/cn/support/matrix#matrix_compatibility

下载地址为:
https://www.elastic.co/cn/downloads/past-releases

6.2 下载 Kibana

到相应地址,下载即可,解压下载后的文件

在这里插入图片描述

6.3 修改配置文件

修改配置文件:vim 安装目录 /config/kibana.yml

# 更多配置信息,详见 https://www.elastic.co/guide/cn/kibana/current/settings.html
server.port: 5601
server.host: "127.0.0.1"
server.name: lqz
elasticsearch.hosts: ["http://localhost:9200/"]

6.4 启动

到安装目录下:

./bin/kibana
# 正常启动

6.5 查看

在浏览器里访问:http://localhost:5601/app/kibana

(如访问不到,尝试删除es中跟kibana相关的索引)

选择 Dev Tools

在这里插入图片描述
在 console 中输入 GET _settings ,查询可以看到如下

在这里插入图片描述

7. Elasticsearch 之 索引操作

具体操作可以查看官方文档
https://www.elastic.co/guide/en/elasticsearch/reference/7.5/indices.html>

官方2版本的中文文档
https://www.elastic.co/guide/cn/elasticsearch/guide/current/index-settings.html

7.1 索引初始化

# 新建一个x1的索引,索引分片数量为5,索引副本数量为1
PUT x1
{
  "settings": {
    "index":{
      "number_of_shards":5,
      "number_of_replicas":1
    }
  }
}


'''
number_of_shards
每个索引的主分片数,默认值是 5 。这个配置在索引创建后不能修改。

number_of_replicas
每个主分片的副本数,默认值是 1 。对于活动的索引库,这个配置可以随时修改。
'''

在这里插入图片描述

# 获取x2索引的配置信息
GET x2/_settings

# 获取所有索引的配置信息
GET _all/_settings

# 同上
GET _settings

7.2 更新索引

# 修改索引副本数量为2
PUT x2/_settings
{
  "number_of_replicas": 2
}

# 如遇到报错:cluster_block_exception
# 这是因为由于ES新节点的数据目录data存储空间不足,导致从master主节点接收同步数据的时候失败,此时ES集群为了保护数据,会自动把索引分片index置为只读read-only
PUT  _all/_settings
{
"index": {
  "blocks": {
    "read_only_allow_delete": false
    }
  }
}

7.3 删除索引

# 删除x2索引
DELETE x2

8. Elasticsearch 之 映射管理

在Elasticsearch 6.0.0或更高版本中创建的索引只包含一个mapping type。 在5.x中使用multiple mapping types创建的索引将继续像以前一样在Elasticsearch 6.x中运行。 Mapping types将在Elasticsearch 7.0.0中完全删除

8.1 映射介绍

在创建索引的时候,可以预先定义字段的类型及相关属性
Es会根据Json数据源的基础类型,猜测你想要映射的字段,将输入的数据转变成可以搜索的索引项。
Mapping是我们自己定义的字段数据类型,同时告诉es如何索引数据及是否可以被搜索
作用:会让索引建立的更加细致和完善

mysql中有建表语句,es中就是映射管理,即便没有类型,文档可以直接插入

8.2 字段数据类型

类型说明
string类型text,keyword
数字类型long,integer,short,byte,double,float
日期类型data
布尔类型boolean
binary类型binary
复杂类型object(实体,对象),nested(列表)
geo类型geo-point,geo-shape(地理位置)
专业类型ip,competion(搜索建议)

8.3 映射参数

属性描述适合类型
store值为yes表示存储,no表示不存储,默认为yesall
indexyes表示分析,no表示不分析,默认为truetext
null_value如果字段为空,可以设置一个默认值,比如"NA"(传过来为空,不能搜索,na可以搜索)all
analyzer可以设置索引和搜索时用的分析器,默认使用的是standard分析器,还可以使用whitespace,simple。都是英文分析器all
include_in_all默认es为每个文档定义一个特殊域_all,它的作用是让每个字段都被搜索到,如果想让某个字段不被搜索到,可以设置为falseall
format时间格式字符串模式date

8.4 创建索引

text 类型会取出词做倒排索引,keyword 不会被分词,原样存储,原样匹配
mapping 类型一旦确定,以后就不能修改了

# 6.x的版本没问题
PUT books
{
  "mappings": {
    "book":{
      "properties":{
        "title":{
          "type":"text",
         	"analyzer": "ik_max_word"
        },
        "price":{
          "type":"integer"
        },
        "addr":{
          "type":"keyword"
        },
        "company":{
          "properties":{
            "name":{"type":"text"},
            "company_addr":{"type":"text"},
            "employee_count":{"type":"integer"}
          }
        },
        "publish_date":{"type":"date","format":"yyy-MM-dd"}       
      }
    }
  }
}

7.x 版本以后

# 7.x及以上,6.x以后,强制一个索引下只能有一个类型,叫_doc  (一个数据库只能建一个表)
PUT books
{
  "mappings": {
    "properties":{
      "title":{
        "type":"text"
      },
      "price":{
        "type":"integer"
      },
      "addr":{
        "type":"keyword"
      },
      "company":{
        "properties":{
          "name":{"type":"text"},
          "company_addr":{"type":"text"},
          "employee_count":{"type":"integer"}
        }
      },
      "publish_date":{"type":"date","format":"yyy-MM-dd"}     
    }
  }
}
# 插入文档
PUT books/_doc/1
{
  "title":"大头儿子小偷爸爸",
  "price":100,  
  "addr":"北京天安门",
  "company":{
    "name":"我爱北京天安门",
    "company_addr":"我的家在东北松花江傻姑娘",
    "employee_count":10
  },
  "publish_date":"2019-08-19"
}

# 测试数据2
PUT books/_doc/2
{
  "title":"白雪公主和十个小矮人",
  "price":"99", # 写字符串会自动转换
  "addr":"黑暗森里",
  "company":{
    "name":"我的家乡在上海",
    "company_addr":"朋友一生一起走",
    "employee_count":10
  },
  "publish_date":"2018-05-19"
}

PUT books/_doc/3   # 这个也可以存
{
  "age":"白雪公主和十个小矮人",
  "name":"xwx"
}

8.5 查看索引

# 查看books索引的mapping
GET books/_mapping

# 获取所有的mapping
GET _all/_mapping

9. Elasticsearch 的增删查改(CURD)

9.1 CURD 之 Create

PUT xwx/_doc/1
{
  "name":"顾老二",
  "age":30,
  "from": "gu",
  "desc": "皮肤黑、武器长、性格直",
  "tags": ["黑", "长", "直"]
}

PUT xwx/_doc/2
{
  "name":"熊大",
  "age":22,
  "from": "ha",
  "desc": "小熊一只",
  "tags": ["黄", "大"]
}

在这里插入图片描述

注意:当执行PUT命令时,如果数据不存在,则新增该条数据,如果数据存在则修改该条数据。

咱们通过GET命令查询一下:

GET xwx/_doc/1

如果使用 PUT 方式来修改,结果如下所示,会将原本的数据代替导致数据缺失

PUT xwx/_doc/1
{
  "desc":"皮肤很黄,武器很长,性格很直",
  "tags":["很黄","很长", "很直"]
}

在这里插入图片描述

9.2 CURD 之 Update

上面出现的问题,我们先恢复成原装。

PUT xwx/_doc/1
{
  "name":"顾老二",
  "age":30,
  "from": "gu",
  "desc": "皮肤黑、武器长、性格直",
  "tags": ["黑", "长", "直"]
}

接下来修改需要使用 POST 方法,如下所示,原本的数据不会缺失

POST xwx/_doc/1/_update
{
  "doc": {
    "desc": "这是修改后",
    "tags": ["哈哈","哈哈", "哈哈"]
  }
}

在这里插入图片描述

现在推荐的写法如下所示

POST /xwx/_update/1
{
  "doc": {
    "desc": "这是推荐的写法",
    "tags": ["哈哈","哈哈", "哈哈"]
  }
}

9.3 CURD 之 Delete

DELETE xwx/_doc/1

通过DELETE命令,就可以删除掉

# 再次获取数值
GET xwx/_doc/1

# found:false 表示查询数据不存在
{
  "_index" : "xwx",
  "_type" : "_doc",
  "_id" : "1",
  "found" : false
}

9.4 CURD 之 Retrieve

我们上面已经不知不觉的使用熟悉这种简单查询方式,通过 GET命令查询指定文档:

GET xwx/_doc/1

10. Elasticsearch 之查询的两种方式

  • 查询字符串(query string),简单查询,就像是像传递URL参数一样去传递查询语句,被称为简单搜索或查询字符串(query string)搜索。

  • 另外一种是通过DSL语句来进行查询,被称为DSL查询(Query DSL),DSL是Elasticsearch提供的一种丰富且灵活的查询语言,该语言以json请求体的形式出现,通过restful请求与Elasticsearch进行交互。

数据准备

PUT xwx/_doc/1
{
  "name":"顾老二",
  "age":30,
  "from": "gu",
  "desc": "皮肤黑、武器长、性格直",
  "tags": ["黑", "长", "直"]
}

PUT xwx/_doc/2
{
  "name":"大娘子",
  "age":18,
  "from":"sheng",
  "desc":"肤白貌美,娇憨可爱",
  "tags":["白", "富","美"]
}

PUT xwx/_doc/3
{
  "name":"龙套偏房",
  "age":22,
  "from":"gu",
  "desc":"mmp,没怎么看,不知道怎么形容",
  "tags":["造数据", "真","难"]
}

PUT xwx/_doc/4
{
  "name":"石头",
  "age":29,
  "from":"gu",
  "desc":"粗中有细,狐假虎威",
  "tags":["粗", "大","猛"]
}

PUT xwx/_doc/5
{
  "name":"魏行首",
  "age":25,
  "from":"广云台",
  "desc":"仿佛兮若轻云之蔽月,飘飘兮若流风之回雪,mmp,最后竟然没有嫁给顾老二!",
  "tags":["闭月","羞花"]
}

在这里插入图片描述

10.1 查询字符串

GET xwx/_doc/_search?q=from:gu

还是使用 GET 命令,通过 _serarch 查询,查询条件是什么呢?条件是 from 属性 是 gu 的人都有哪些。别忘了_search 和 from 属性中间的英文分隔符?,结果如下

#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
  "took" : 19,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 0.6329006,
    "hits" : [
      {
        "_index" : "xwx",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.6329006,
        "_source" : {
          "name" : "顾老二",
          "age" : 30,
          "from" : "gu",
          "desc" : "皮肤黑、武器长、性格直",
          "tags" : [
            "黑",
            "长",
            "直"
          ]
        }
      },
      {
        "_index" : "xwx",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.6329006,
        "_source" : {
          "name" : "龙套偏房",
          "age" : 22,
          "from" : "gu",
          "desc" : "mmp,没怎么看,不知道怎么形容",
          "tags" : [
            "造数据",
            "真",
            "难"
          ]
        }
      },
      {
        "_index" : "xwx",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 0.6329006,
        "_source" : {
          "name" : "石头",
          "age" : 29,
          "from" : "gu",
          "desc" : "粗中有细,狐假虎威",
          "tags" : [
            "粗",
            "大",
            "猛"
          ]
        }
      }
    ]
  }
}

我们来重点说下hits,hits 是返回的结果集(如上是所有 from 属性为 gu 的结果集)。重点中的重点是 _score 得分,得分是什么呢?根据算法算出跟查询条件的匹配度,匹配度高得分就高。

10.2 结构化查询

现在使用DSL方式,来完成刚才的查询

GET xwx/_doc/_search
{
  "query": {
    "match": {
      "from": "gu"
    }
  }
}

上例,查询条件是一步步构建出来的,将查询条件添加到 match 中即可,而 match 则是查询所有 from字段的值中含有 gu 的结果就会返回。

11 term 与 match 查询

11.1 match 系列之 match(按条件查询)

match 查询如下所示

GET xwx/_doc/_search
{
  "query": {
    "match": {
      "from": "gu"
    }
  }
}

11.2 match 系列之 match_all(查询全部)

除了按条件查询之外,我们还可以查询 xwx 索引下的 doc 类型中的所有文档,那就是查询全部

GET xwx/_doc/_search
{
  "query": {
    "match_all": {}
  }
}

match_all 的值为空,表示没有查询条件,那就是查询全部。就像 select * from table_name 一样

11.2 match 系列之 match_phrase(短语查询)

现在已经对 match 有了基本的了解,match 查询的是散列映射,包含了我们希望搜索的字段和字符串。也就说,只要文档中只要有我们希望的那个关键字,但也因此带来了一些问题。
首先来创建一些示例:

PUT t1/_doc/1
{
  "title": "中国是世界上人口最多的国家"
}
PUT t1/_doc/2
{
  "title": "目前美国是世界上军事实力最强大的国家"
}
PUT t1/_doc/3
{
  "title": "北京是中国的首都"
}

在这里插入图片描述
现在,当我们以 中国 作为搜索条件,我们希望只返回和中国相关的文档。首先来使用 match 查询:

GET t1/_doc/_search
{
  "query": {
    "match": {
      "title": "中国"
    }
  }
}

结果如下所示,虽然如期的返回了中国的文档。但是却把和美国的文档也返回了

因为这是 elasticsearch 在内部对文档做分词的时候,对于中文来说,就是一个字一个字分的,所以,我们搜 中国都符合条件,返回,而美国的也符合。

#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
  "took" : 4,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 0.71622837,
    "hits" : [
      {
        "_index" : "t1",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.71622837,
        "_source" : {
          "title" : "北京是中国的首都"
        }
      },
      {
        "_index" : "t1",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.6536093,
        "_source" : {
          "title" : "中国是世界上人口最多的国家"
        }
      },
      {
        "_index" : "t1",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.1656832,
        "_source" : {
          "title" : "目前美国是世界上军事实力最强大的国家"
        }
      }
    ]
  }
}

而我们认为中国是个短语,是一个有具体含义的词。所以elasticsearch在处理中文分词方面比较弱势。后面会有对中文的插件。

但目前我们还有办法解决,那就是使用短语查询:

GET t1/_doc/_search
{
  "query": {
    "match_phrase": {
      "title": {
        "query": "中国"
      }
    }
  }
}

这里match_phrase是在文档中搜索指定的词组,而中国则正是一个词组,所以愉快的返回了。
那么,现在我们要想搜索中国和世界相关的文档,但又忘记其余部分了,怎么做呢?用 match 也不行,那就继续用 match_phrase 试试:

GET t1/_doc/_search
{
  "query": {
    "match_phrase": {
      "title": "中国世界"
    }
  }
}

很明显结果为空,因为没有中国世界这个短语

我们搜索中国世界这两个指定词组时,但又不清楚两个词组之间有多少别的词间隔。那么在搜的时候就要留有一些余地。这时就要用到了slop了。相当于正则中的中国.*?世界。这个间隔默认为0,导致我们刚才没有搜到,现在我们指定一个间隔

GET t1/_doc/_search
{
  "query": {
    "match_phrase": {
      "title": {
        "query": "中国世界",
        "slop": 2
      }
    }
  }
}

现在,两个词组之间有了2个词的间隔,这个时候,就可以查询到结果了:

#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.99876255,
    "hits" : [
      {
        "_index" : "t1",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.99876255,
        "_source" : {
          "title" : "中国是世界上人口最多的国家"
        }
      }
    ]
  }
}

11.3 match 系列之 match_phrase_prefix(最左前缀查询)

当准备搜索 beautiful girl 词语时。但单词 beautiful 拼到 bea 就不知道往下怎么拼了。这个时候,elasticsearch 就可以看自己的词库有啥 bea 开头的词,结果还真发现了两个:

准备数据

PUT t3/_doc/1
{
  "title": "maggie",
  "desc": "beautiful girl you are beautiful so"
}
PUT t3/_doc/2
{
  "title": "sun and beach",
  "desc": "I like basking on the beach"
}

在这里插入图片描述
但这里用 matchmatch_phrase 都不太合适,因为输入的不是完整的词。
可以用 match_phrase_prefix 来搞:

GET t3/_doc/_search
{
  "query": {
    "match_phrase_prefix": {
      "desc": "bea"
    }
  }
}

结果如下

#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
  "took" : 4,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.9530774,
    "hits" : [
      {
        "_index" : "t3",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.9530774,
        "_source" : {
          "title" : "maggie",
          "desc" : "beautiful girl you are beautiful so"
        }
      },
      {
        "_index" : "t3",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.6931472,
        "_source" : {
          "title" : "sun and beach",
          "desc" : "I like basking on the beach"
        }
      }
    ]
  }
}

前缀查询是短语查询类似,但前缀查询可以更进一步的搜索词组,只不过它是和词组中最后一个词条进行前缀匹配(如搜这样的 you are bea)。应用也非常的广泛,比如搜索框的提示信息,当使用这种行为进行搜索时,最好通过 max_expansions 来设置最大的前缀扩展数量,因为产生的结果会是一个很大的集合,不加限制的话,影响查询性能。

GET t3/_doc/_search
{
  "query": {
    "match_phrase_prefix": {
      "desc": {
        "query": "bea",
        "max_expansions": 1
      }
    }
  }
}

结果如下

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.6931472,
    "hits" : [
      {
        "_index" : "t3",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.6931472,
        "_source" : {
          "title" : "sun and beach",
          "desc" : "I like basking on the beach"
        }
      }
    ]
  }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你是一个还没有安装好自己的 Elasticsearch 的开发者,你可以参考之前的文章 "Elastic: 开发者上手指南" 来安装自己的 Elasticsearch 及 Kibana。这篇文章提供了详细的步骤和指导,帮助你轻松上手 Elasticsearch。 一旦你安装好了 Elasticsearch,你可以继续学习如何使用 Elasticsearch ingest 节点来丰富日志和指标。这个过程可以帮助你更好地处理和分析数据,并提供更多有用的信息。 此外,如果你对 Elasticsearch 的 refresh 和 flush 操作感兴趣,你也可以查阅相关的指南,它们会进一步解释这些操作的作用和用法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Elastic:开发者上手指南](https://blog.csdn.net/UbuntuTouch/article/details/102728604)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [ElasticsearchElasticsearch SQL介绍及实例 (一)](https://blog.csdn.net/UbuntuTouch/article/details/105658911)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值