前言
Elaticsearch,简称为 ES, 是一个开源的高扩展的分布式全文搜索引擎 (这里说到的全文搜索引擎指的是目前广泛应用的主流搜索引擎)。与传统型关系数据库不同,Elaticsearch使用的是倒排索引,它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。
例如百度、谷歌之类的搜索引擎,它们都是根据网页中的关键字生成索引的,当我们在这类搜索引擎输入关键字进行搜索时,它们会根据关键字去匹配索引,然后将索引对应的所有网页返回;除了这类搜索引擎之外,还一些非结构化的数据文本等,对于这些内容的搜索,关系型数据库搜索不是能很好的支持。而且一般传统数据库,全文检索都实现的很鸡肋,因为一般也没人用数据库存文本字段(除了wordpress,之前折腾wordpress时,把数据库删了,文章直接就没了,后面发现wordpress竟然把文章存在数据库里 == )。当进行全文检索时,需要扫描整个表,如果数据量大的话即使对 SQL 的语法优化,也收效甚微。即使建立了索引,后期维护起来也比较麻烦,进行插入和更新操作时都会重新构建索引。 全文搜索引擎的适用场景:
- 搜索的数据对象是大量的非结构化的文本数据。
- 文件记录量达到数十万或数百万个甚至更多。
- 支持大量基于交互式文本的查询。
- 需求非常灵活的全文搜索查询。
- 对高度相关的搜索结果的有特殊需求,但是没有可用的关系数据库可以满足。
- 对不同记录类型、非文本数据操作或安全事务处理的需求相对较少的情况。
下载安装
Elasticsearch 的官方地址,下载完后直接解压;
进入 bin 文件目录,点击 elasticsearch.bat 文件启动 ES 服务
打开地址:http://localhost:9200
,测试是否启动成功
RESTful
在SpringMVC中有提到过。
REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就 是 RESTful。Web 应用程序最重要的 REST 原则是,客户端和服务器之间的交互在请求之 间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。如果服务 器在请求之间的任何时间点重启,客户端不会得到通知。此外,无状态请求可以由任何可用 服务器回答,这十分适合云计算之类的环境。客户端可以缓存数据以改进性能。 在服务器端,应用程序状态和功能可以分为各种资源。资源是一个有趣的概念实体,它 向客户端公开。资源的例子有:应用程序对象、数据库记录、算法等等。每个资源都使用 URI (Universal Resource Identifier) 得到一个唯一的地址。所有资源都共享统一的接口,以便在客 户端和服务器之间传输状态。使用的是标准的 HTTP 方法,比如 GET、PUT、POST 和 DELETE。
在 REST 样式的 Web 服务中,每个资源都有一个地址。资源本身都是方法调用的目 标,方法列表对所有资源都是一样的。这些方法都是标准方法,包括 HTTP GET、POST、 PUT、DELETE,还可能包括 HEAD 和 OPTIONS。简单的理解就是,如果想要访问互联 网上的资源,就必须向资源所在的服务器发出请求,请求体中必须包含资源的网络路径,以 及对资源进行的操作(增删改查)。
第三方工具
使用Elasticsearch服务器发请求时必须包含HTTP 标准的方法,而大部分浏览器默认发送的只有 GET 和 POST 请求。所以为了能方便地进行客户端的访问,
我们可以使用Postman 网页调试工具配合使用。
Postman下载安装后,按照提示填写信息,然后随便创建一个team就可以了;
使用Elasticsearch服务器发请求时必须包含HTTP 标准的方法,而大部分浏览器默认发送的只有 GET 和 POST 请求。所以为了能方便地进行客户端的访问,
我们可以使用以下几种工具可配合使用。
- Kibana,Elastic官方提供的ES可视化工具
- Postman ,功能强大网页调试工具,可用于完成ES各种请求
- Chrome的ES插件
- elasticsearch-head,界面简陋,但是使用十分方便的ES在线可视化工具
数据格式
Elasticsearch 是面向文档型数据库,一条数据对应的就是一个文档。
与MySQL的类比:
ES 里的 Index 可以看做一个库,而 Types 相当于表,Documents 则相当于表的行。 这里 Types 的概念已经被逐渐弱化,Elasticsearch 6.X 中,一个 index 下已经只能包含一个 type,Elasticsearch 7.X 中, Type 的概念已经被删除了
用 JSON 作为文档序列化的格式,比如一条用户信息:
代码语言:javascript复制{
"name" : "Ahzoo",
"age" : 18,
"birthDate": "01/23",
"about" : "nothing",
"interests": [ "sports", "music" ]
}
HTTP操作
Postman
索引操作
为了方便演示RESTful风格,这里使用的是Postman进行操作,如果不用RESTful风格,可直接跳到Kibana
打开Postman,按照提示进行初始化设置;
进入Postman界面后,新建一个Collection;
创建索引
相当于关系型数据库中的创建数据库
点击右侧加号;输入一个PUT命令:
代码语言:javascript复制PUT http://127.0.0.1:9200/shopping
然后点击Send,可以看到创建成功的提示 返回结果:
代码语言:javascript复制{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "shopping"
}
重复添加时会报错: 返回结果:
代码语言:javascript复制{
"error" : {
"root_cause" : [
{
"type" : "resource_already_exists_exception",
"reason" : "index [shopping/oTiQnf9UT--dwgsZ_2wBow] already exists",
"index_uuid" : "oTiQnf9UT--dwgsZ_2wBow",
"index" : "shopping"
}
],
"type" : "resource_already_exists_exception",
"reason" : "index [shopping/oTiQnf9UT--dwgsZ_2wBow] already exists",
"index_uuid" : "oTiQnf9UT--dwgsZ_2wBow",
"index" : "shopping"
},
"status" : 400
}
查询索引
输入一个GET命令,来查询所有索引;(cat 表示查看的意思,indices 表示索引,相当于像 MySQL 中的 show tables)
代码语言:javascript复制GET http://127.0.0.1:9200/_cat/indices?v
返回结果:
代码语言:javascript复制health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open .geoip_databases fjfmnkm2RZKMHtGbBQGweg 1 0 41 39 40.1mb 40.1mb
green open .kibana_7.15.0_001 mKyI2n3oSaK-U7-BIepohA 1 0 51 5 2.3mb 2.3mb
green open .apm-custom-link 4m9W5TxCRJSs8I6GqDepMw 1 0 0 0 208b 208b
green open .apm-agent-configuration 731dsjx0TaWdnmGqyKBvQQ 1 0 0 0 208b 208b
green open .kibana-event-log-7.15.0-000001 2__Yx8BARWGwOgCarYgezA 1 0 1 0 6kb 6kb
green open .kibana_task_manager_7.15.0_001 bWnZfG6aQPyCXa8j23Mimw 1 0 15 3825 540.5kb 540.5kb
yellow open shopping VxYeY2FBS6a8wZxgWEdGtQ 1 1 0 0 208b 208b
查询单个索引
代码语言:javascript复制GET http://127.0.0.1:9200/shopping
返回结果:
代码语言:javascript复制{
"shopping": {
"aliases": {},
"mappings": {},
"settings": {
"index": {
"routing": {
"allocation": {
"include": {
"_tier_preference": "data_content"
}
}
},
"number_of_shards": "1",
"provided_name": "shopping",
"creation_date": "1633513773067",
"number_of_replicas": "1",
"uuid": "VxYeY2FBS6a8wZxgWEdGtQ",
"version": {
"created": "7150099"
}
}
}
}
}
删除索引
代码语言:javascript复制DELETE http://127.0.0.1:9200/shopping
返回结果:
代码语言:javascript复制{
"acknowledged" : true
}
文档操作
创建文档
这里的文档就相当于MySQL中的表中的数据
发送一个POST请求,创建文档,文档的格式为JSON:
- POST
选择POST请求(由于此处没有指定ID为非幂等性操作,所以只能用POST):
代码语言:javascript复制简单理解幂等性:多次操作与一次操作的结果相同,即为幂等性操作;反之 此例中由于没有指定ID,所以ID为随机生成,导致多次操作与一次操作的结果不同
POST http://127.0.0.1:9200/shopping/_doc
输入请求体:点击Body,点击raw,格式选择JSON,并在输入框输入请求体(请求完成后记得把请求体删除,否则遇到不需要请求体的命令时会报错)
代码语言:javascript复制{
"title":"HUAWEI Mate 40 Pro",
"category":"华为手机",
"images":"https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
"price":6299
}
然后点击Send发送请求;
返回结果(附解释):
代码语言:javascript复制{
"_index"【索引】: "shopping",
"_type"【类型-文档】: "_doc",
"_id"【唯一标识】: "qHRAVXwBGcQwpwap0CcF", //可以类比为 MySQL 中的主键,随机生成
"_version"【版本】: 1,
"result"【结果】: "created",//这里的 create 表示创建成功
"_shards"【分片】: {
"total"【分片 - 总数】: 2,
"successful"【分片 - 成功】: 1,
"failed"【分片 - 失败】: 0
},
"_seq_no": 0,
"_primary_term": 1
}
- PUT/POST
上面的数据创建后,由于没有指定数据唯一性标识(ID)(也就是主键),默认情况下,ES 服务器会随机生成一个。 如果想要自定义唯一性标识,需要在创建时指定(此时就变成了幂等性操作,因此可以使用POST和PUT两种请求方式):
代码语言:javascript复制POST/PUT http://127.0.0.1:9200/shopping/_doc/1
请求体:(请求完成后记得把请求体删除,否则遇到不需要请求体的命令时会报错)
代码语言:javascript复制{
"title":"HUAWEI Mate 40 Pro",
"category":"华为手机",
"images":"https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
"price":6299
}
返回结果:
代码语言:javascript复制{
"_index": "shopping",
"_type": "_doc",
"_id": "1", // 可以看到ID为指定的 1
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 1,
"_primary_term": 1
}
查看文档
- 通过主键(ID)查询,此处的1为刚才创建的ID
GET http://127.0.0.1:9200/shopping/_doc/1
返回结果:
代码语言:javascript复制{
"_index": "shopping",
"_type": "_doc",
"_id": "1",
"_version": 2,
"_seq_no": 2,
"_primary_term": 1,
"found": **true**,
"_source": {
"title": "HUAWEI Mate 40 Pro",
"category": "华为手机",
"images": "https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
"price": 6299
}
}
- 通过
_search
查询目标索引全部数据
http://127.0.0.1:9200/shopping/_search
代码语言:javascript复制{
"took": 3,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "shopping",
"_type": "_doc",
"_id": "qHRAVXwBGcQwpwap0CcF",
"_score": 1.0,
"_source": {
"title": "HUAWEI Mate 40 Pro",
"category": "华为手机",
"images": "https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
"price": 6299
}
},
{
"_index": "shopping",
"_type": "_doc",
"_id": "1",
"_score": 1.0,
"_source": {
"title": "HUAWEI Mate 40 Pro",
"category": "华为手机",
"images": "https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
"price": 6299
}
}
]
}
}
修改文档
- 全量修改
POST/PUT http://127.0.0.1:9200/shopping/_doc/1
请求体:(请求完成后记得把请求体删除,否则遇到不需要请求体的命令时会报错)
代码语言:javascript复制{
"title":"HUAWEI Mate 40",
"category":"华为手机",
"images":"https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
"price":6099
}
点击Send发送请求:
返回结果:
代码语言:javascript复制{
"_index": "shopping",
"_type": "_doc",
"_id": "1",
"_version"【版本】: 3,
"result"【结果】: "updated",// updated 表示数据被更新
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 3,
"_primary_term": 1
}
- 局部修改(非幂等性)
POST http://127.0.0.1:9200/shopping/_update/1
请求体:
代码语言:javascript复制{
"doc": {
"category":"国产手机" // 点名要修改的字段为"category"
//这里可以写其它需要修改的字段
}
}
返回结果:
代码语言:javascript复制{
"_index": "shopping",
"_type": "_doc",
"_id": "1",
"_version": 2,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 16,
"_primary_term": 1
}
删除文档
- 通过ID删除
DELETE http://127.0.0.1:9200/shopping/_doc/1
返回结果:
代码语言:javascript复制{
"_index": "shopping",
"_type": "_doc",
"_id": "1",
"_version": 5,
"result": "deleted",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 5,
"_primary_term": 1
}
- 通过条件删除
POST http://127.0.0.1:9200/shopping/_delete_by_query
请求体:
代码语言:javascript复制{
"query":{
"match":{
"price":6299
}
}
}
返回结果:
代码语言:javascript复制{
"took"【请求时间】: 24,
"timed_out"【是否超时】: false,
"total"【总数】: 3,
"deleted"【删除数量】: 3,
"batches": 1,
"version_conflicts": 0,
"noops": 0,
"retries": {
"bulk": 0,
"search": 0
},
"throttled_millis": 0,
"requests_per_second": -1.0,
"throttled_until_millis": 0,
"failures": []
}
同理如果要删除索引下全部数据,只需要改请求体条件即可:
代码语言:javascript复制{
"query": {
"match_all": {}
}
}
Kibana
打开Kibana的bin路径下的kibana.bat启动Kibana;
然后浏览器访问5601端口,点击Explore on my own;
在左侧菜单找到Dev Tools;
索引操作
创建索引
相当于关系型数据库中的创建数据库
输入一个PUT命令:
代码语言:javascript复制PUT shopping
错误写法(不能有空行):
代码语言:javascript复制PUT shopping
点击代码右侧的启动按钮,可以在右侧看到创建成功的提示 返回结果:
代码语言:javascript复制{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "shopping"
}
重复添加时会报错: 返回结果:
代码语言:javascript复制{
"error" : {
"root_cause" : [
{
"type" : "resource_already_exists_exception",
"reason" : "index [shopping/oTiQnf9UT--dwgsZ_2wBow] already exists",
"index_uuid" : "oTiQnf9UT--dwgsZ_2wBow",
"index" : "shopping"
}
],
"type" : "resource_already_exists_exception",
"reason" : "index [shopping/oTiQnf9UT--dwgsZ_2wBow] already exists",
"index_uuid" : "oTiQnf9UT--dwgsZ_2wBow",
"index" : "shopping"
},
"status" : 400
}
查询索引
输入一个GET命令,来查询所有索引;(cat 表示查看的意思,indices 表示索引,相当于像 MySQL 中的 show tables)
代码语言:javascript复制GET _cat/indices?v
返回结果:
代码语言:javascript复制health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open .geoip_databases fjfmnkm2RZKMHtGbBQGweg 1 0 41 39 40.1mb 40.1mb
green open .kibana_7.15.0_001 mKyI2n3oSaK-U7-BIepohA 1 0 51 3 2.3mb 2.3mb
green open .apm-custom-link 4m9W5TxCRJSs8I6GqDepMw 1 0 0 0 208b 208b
green open .apm-agent-configuration 731dsjx0TaWdnmGqyKBvQQ 1 0 0 0 208b 208b
green open .kibana-event-log-7.15.0-000001 2__Yx8BARWGwOgCarYgezA 1 0 1 0 6kb 6kb
green open .kibana_task_manager_7.15.0_001 bWnZfG6aQPyCXa8j23Mimw 1 0 15 2124 286.4kb 286.4kb
yellow open shopping pjEDILI4TjCq1zG2rGfiww 1 1 0 0 208b 208b
可以看到ElasticSearch请求方式用小写也能执行,但是左侧会报错误提醒
查询单个索引
代码语言:javascript复制GET shopping
返回结果:
代码语言:javascript复制{
"shopping" : {
"aliases" : { },
"mappings" : { },
"settings" : {
"index" : {
"routing" : {
"allocation" : {
"include" : {
"_tier_preference" : "data_content"
}
}
},
"number_of_shards" : "1",
"provided_name" : "shopping",
"creation_date" : "1633512085101",
"number_of_replicas" : "1",
"uuid" : "pjEDILI4TjCq1zG2rGfiww",
"version" : {
"created" : "7150099"
}
}
}
}
}
删除索引
代码语言:javascript复制DELETE shopping
返回结果:
代码语言:javascript复制{
"acknowledged" : true
}
文档操作
创建文档
这里的文档就相当于MySQL中的表中的数据
发送一个POST请求,创建文档,文档的格式为JSON:
- POST
选择POST请求(由于此处没有指定ID为非幂等性操作,所以只能用POST):
代码语言:javascript复制简单理解幂等性:多次操作与一次操作的结果相同,即为幂等性操作;反之 此例中由于没有指定ID,所以ID为随机生成,导致多次操作与一次操作的结果不同
POST shopping/_doc
{
"title":"HUAWEI Mate 40 Pro",
"category":"华为手机",
"images":"https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
"price":6299
}
点击右侧运行按钮运行
返回结果(附解释):
代码语言:javascript复制{
"_index"【索引】: "shopping",
"_type"【类型-文档】: "_doc",
"_id"【唯一标识】: "qXSbVXwBGcQwpwaptCcq", //可以类比为 MySQL 中的主键,随机生成
"_version"【版本】: 1, //对数据的操作,都会更新版本
"result"【结果】: "created",//这里的 create 表示创建成功
"_shards"【分片】: {
"total"【分片 - 总数】: 2,
"successful"【分片 - 成功】: 1,
"failed"【分片 - 失败】: 0
},
"_seq_no": 6,
"_primary_term": 1
}
- PUT/POST
上面的数据创建后,由于没有指定数据唯一性标识(ID)(也就是主键),默认情况下,ES 服务器会随机生成一个。 如果想要自定义唯一性标识,需要在创建时指定(此时就变成了幂等性操作,因此可以使用POST和PUT两种请求方式)
代码语言:javascript复制PUT shopping/_doc/1
{
"title":"HUAWEI Mate 40 Pro",
"category":"华为手机",
"images":"https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
"price":6299
}
代码语言:javascript复制POST shopping/_doc/1
{
"title":"HUAWEI Mate 40 Pro",
"category":"华为手机",
"images":"https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
"price":6299
}
返回结果:
代码语言:javascript复制{
"_index": "shopping",
"_type": "_doc",
"_id": "1", // 可以看到ID为指定的 1
"_version": 2,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 8,
"_primary_term": 1
}
查看文档
- 通过主键(ID)查询,此处的1为刚才创建的ID
GET shopping/_doc/1
返回结果:
代码语言:javascript复制{
"_index" : "shopping",
"_type" : "_doc",
"_id" : "1",
"_version" : 2,
"_seq_no" : 8,
"_primary_term" : 1,
"found" : true,
"_source" : {
"title" : "HUAWEI Mate 40 Pro",
"category" : "华为手机",
"images" : "https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
"price" : 6299
}
}
- 通过
_search
查询目标索引全部数据
GET shopping/_search
代码语言:javascript复制{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "shopping",
"_type" : "_doc",
"_id" : "qHRAVXwBGcQwpwap0CcF",
"_score" : 1.0,
"_source" : {
"title" : "HUAWEI Mate 40 Pro",
"category" : "华为手机",
"images" : "https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
"price" : 6299
}
},
{
"_index" : "shopping",
"_type" : "_doc",
"_id" : "qXSbVXwBGcQwpwaptCcq",
"_score" : 1.0,
"_source" : {
"title" : "HUAWEI Mate 40 Pro",
"category" : "华为手机",
"images" : "https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
"price" : 6299
}
},
{
"_index" : "shopping",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"title" : "HUAWEI Mate 40 Pro",
"category" : "华为手机",
"images" : "https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
"price" : 6299
}
}
]
}
}
修改文档
- 全量修改
请求体:(请求完成后记得把请求体删除,否则遇到不需要请求体的命令时会报错)
代码语言:javascript复制PUT shopping/_doc/1
{
"title":"HUAWEI Mate 40",
"category":"华为手机",
"images":"https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
"price":6099
}
返回结果:
代码语言:javascript复制{
"_index" : "shopping",
"_type" : "_doc",
"_id" : "1",
"_version" : 3,
"result" : "updated", // updated 表示数据被更新
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 9,
"_primary_term" : 1
}
- 局部修改(非幂等性)
POST http://127.0.0.1:9200/shopping/_update/1
请求体:
代码语言:javascript复制POST /shopping/_update/1
{
"doc": {
"title":"华为 Mate 40",//点名要修改的字段为"title"
"category":"国产手机" //点名要修改的字段为"category"
//这里可以写其它需要修改的字段
}
}
返回结果
代码语言:javascript复制{
"_index" : "shopping",
"_type" : "_doc",
"_id" : "1",
"_version" : 4,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 10,
"_primary_term" : 1
}
删除文档
- 通过ID删除
DELETE /shopping/_doc/1
返回结果:
代码语言:javascript复制{
"_index" : "shopping",
"_type" : "_doc",
"_id" : "1",
"_version" : 5,
"result" : "deleted",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 11,
"_primary_term" : 1
}
- 通过条件删除
POST /shopping/_delete_by_query
{
"query":{
"match":{
"price":6299
}
}
}
返回结果:
代码语言:javascript复制{
"took" 【请求时间】: 521,
"timed_out" 【是否超时】: false,
"total" 【总数】: 2,
"deleted" 【删除数量】: 2,
"batches" : 1,
"version_conflicts" : 0,
"noops" : 0,
"retries" : {
"bulk" : 0,
"search" : 0
},
"throttled_millis" : 0,
"requests_per_second" : -1.0,
"throttled_until_millis" : 0,
"failures" : [ ]
}
同理如果要删除索引下全部数据,只需要改请求体条件即可:
代码语言:javascript复制{
"query": {
"match_all": {}
}
}
对比
一图简单对比Postman和Kibana使用ES命令方式区别:
由于后面示例都是用的Kibana,继续用Postman的可自行参照此图,根据示例中的Kibana进行类比
映射关系
索引库(index)中的映射类似于数据库(database)中的表结构(table)。 创建数据库表需要设置字段名称,类型,长度,约束等;索引库也一样,需要知道这个类型 下有哪些字段,每个字段有哪些约束信息,这就叫做映射(mapping)。
映射数据说明:
- 字段名:任意填写,下面指定许多属性,例如:title、subtitle、images、price
- type:类型,Elasticsearch 中支持的数据类型非常丰富,说几个关键的:
- String 类型,又分两种: text:可分词
- keyword:不可分词,数据会作为完整字段进行匹配
- Numerical:数值类型,分两类
- 基本数据类型:long、integer、short、byte、double、float、half_float
- 浮点数的高精度类型:scaled_float
- Date:日期类型
- Array:数组类型
- Object:对象
- index:是否索引,默认为 true,也就是说你不进行任何配置,所有字段都会被索引。
- true:字段会被索引,则可以用来进行搜索
- false:字段不会被索引,不能用来搜索
- store:是否将数据进行独立存储,默认为 false 原始的文本会存储在_source 里面,默认情况下其他提取出来的字段都不是独立存储 的,是从_source 里面提取出来的。当然你也可以独立的存储某个字段,只要设置 “store”: true 即可,获取独立存储的字段要比从_source 中解析快得多,但是也会占用 更多的空间,所以要根据实际业务需求来设置。
- analyzer:分词器,这里的 ik_max_word 即使用 ik 分词器
创建映射关系
- 方法一:
首先创建索引
代码语言:javascript复制PUT student
然后创建映射关系
代码语言:javascript复制PUT student/_mapping
{
"properties": {
"name":{
"type": "text",
"index": true
},
"nickname":{
"type": "text",
"index": true
},
"sex":{
"type": "keyword",
"index": true
},
"age":{
"type": "long",
"index": false
}
}
}
返回结果:
代码语言:javascript复制{
"acknowledged" : true
}
- 方法二: 直接创建索引并与映射关联
PUT student2
{
"settings": {},
"mappings": {
"properties": {
"name":{
"type": "text",
"index": true
},
"nickname":{
"type": "keyword",
"index": true
},
"sex":{
"type": "keyword",
"index": true
},
"age":{
"type": "long",
"index": false
}
}
}
}
返回结果:
代码语言:javascript复制{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "student2"
}
查看映射关系
代码语言:javascript复制GET student/_mapping
返回结果:
代码语言:javascript复制{
"student" : {
"mappings" : {
"properties" : {
"age" : {
"type" : "long",
"index" : false
},
"name" : {
"type" : "text"
},
"nickname" : {
"type" : "text"
},
"sex" : {
"type" : "keyword"
}
}
}
}
}
高级查询
为了方便演示,这里不使用系统自动给的映射,而是自行创建映射
代码语言:javascript复制PUT phone
{
"settings": {},
"mappings": {
"properties": {
"name":{
"type": "text",
"index": true
},
"vendor":{
"type": "keyword",
"index": true
},
"pid":{
"type": "long",
"index": false
},
"price":{
"type": "long",
"index": true
},
"content":{
"type": "text",
"index": true
},
"area":{
"type": "keyword",
"index": true
}
}
}
}
创建完映射后,创建数据
代码语言:javascript复制POST /phone/_doc/1001 //这里的_doc即为文档类型,ElasticSearch 7.0已不支持自定义,只能为_doc
{
"name":"小米手机",
"vendor":"小米",
"pid":"1001",
"price":3999 ,
"content":"MIUI Based on Android OS",
"area": "China"
}
POST /phone/_doc/1002
{
"name":"小米手机Pro",
"vendor":"小米",
"pid":"1002",
"price":4999 ,
"content":"MIUI Not based on Harmony OS",
"area": "China"
}
POST /phone/_doc/1003
{
"name":"华为手机",
"vendor":"华为",、
"pid":"1003",
"price":4488 ,
"content":"HarmonyOS Based on Harmony OS",
"area": "China"
}
POST /phone/_doc/1004
{
"name":"华为手机",
"vendor":"华为",
"pid":"1004",
"price":6488,
"content":"HarmonyOS Not based on Android OS",
"area": "China"
}
POST /phone/_doc/1005
{
"name":"苹果手机",
"vendor":"Apple",
"pid":"1005",
"price":5199,
"content":"IOS Not based on Android OS",
"area": "American"
}
POST /phone/_doc/1006
{
"name":"苹果手机",
"vendor":"Apple",
"pid":"1006",
"price":7999,
"content":"IOS Not based on Harmony OS",
"area": "American"
}
全量查询(match_all)
代码语言:javascript复制GET phone/_search
{
"query": { // "query":这里的 query 代表一个查询对象,里面可以有不同的查询属性
"match_all": {} // "match_all":查询类型,例如:match_all(代表查询所有), match,term , range 等等;
// "match_all":{查询条件}:match_all下写查询条件,根据类型的不同,写法也有差异
}
}
代码语言:javascript复制{
"took" 【查询花费时间,单位毫秒】: 0,
"timed_out"【是否超时】 : false,
"_shards"【分片信息】 : {
"total"【总数】 : 1,
"successful"【成功】 : 1,
"skipped" 【忽略】: 0,
"failed"【失败】 : 0
},
"hits"【搜索命中结果】 : {
"total" 【搜索条件匹配的文档总数】: {
"value"【总命中计数的值】 : 6,
"relation"【计数规则】 : "eq" //eq 表示计数准确, gte 表示计数不准确
},
"max_score" 【匹配度分值】: 1.0,
"hits" 【命中结果集合】: [
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1001",
"_score" : 1.0,
"_source" : {
"name" : "小米手机",
"vendor" : "小米",
"pid" : "1001",
"price" : 3999,
"content" : "MIUI Based on Android OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1002",
"_score" : 1.0,
"_source" : {
"name" : "小米手机Pro",
"vendor" : "小米",
"pid" : "1002",
"price" : 4999,
"content" : "MIUI Not based on Harmony OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1003",
"_score" : 1.0,
"_source" : {
"name" : "华为手机",
"vendor" : "华为",
"pid" : "1003",
"price" : 4488,
"content" : "HarmonyOS Based on Harmony OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1004",
"_score" : 1.0,
"_source" : {
"name" : "华为手机",
"vendor" : "华为",
"pid" : "1004",
"price" : 6488,
"content" : "HarmonyOS Not based on Android OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1005",
"_score" : 1.0,
"_source" : {
"name" : "苹果手机",
"vendor" : "Apple",
"pid" : "1005",
"price" : 5199,
"content" : "IOS Not based on Android OS",
"area" : "American"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1006",
"_score" : 1.0,
"_source" : {
"name" : "苹果手机",
"vendor" : "Apple",
"pid" : "1006",
"price" : 7999,
"content" : "IOS Not based on Harmony OS",
"area" : "American"
}
}
]
}
}
匹配查询(match)
match 匹配类型查询,会把查询条件进行分词,然后进行查询,多个词条之间是 or 的关系 1)直接通过请求路径查询(不推荐,中文容易出现乱码)
代码语言:javascript复制GET phone/_search?q=content:OS Android Not on
返回结果:
代码语言:javascript复制{
"took" : 5,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 6,
"relation" : "eq"
},
"max_score" : 1.2530423,
"hits" : [
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1004",
"_score" : 1.2530423,
"_source" : {
"name" : "华为手机",
"vendor" : "华为",
"pid" : "1004",
"price" : 6488,
"content" : "HarmonyOS Not based on Android OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1005",
"_score" : 1.2530423,
"_source" : {
"name" : "苹果手机",
"vendor" : "Apple",
"pid" : "1005",
"price" : 5199,
"content" : "IOS Not based on Android OS",
"area" : "American"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1001",
"_score" : 0.88390386,
"_source" : {
"name" : "小米手机",
"vendor" : "小米",
"pid" : "1001",
"price" : 3999,
"content" : "MIUI Based on Android OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1002",
"_score" : 0.5761833,
"_source" : {
"name" : "小米手机Pro",
"vendor" : "小米",
"pid" : "1002",
"price" : 4999,
"content" : "MIUI Not based on Harmony OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1006",
"_score" : 0.5761833,
"_source" : {
"name" : "苹果手机",
"vendor" : "Apple",
"pid" : "1006",
"price" : 7999,
"content" : "IOS Not based on Harmony OS",
"area" : "American"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1003",
"_score" : 0.15571001,
"_source" : {
"name" : "华为手机",
"vendor" : "华为",
"pid" : "1003",
"price" : 4488,
"content" : "HarmonyOS Based on Harmony OS",
"area" : "China"
}
}
]
}
}
查询条件被自动分词,所有content字段中包含“OS、Android、Not、on”的文档均会被检索出来
2)通过请求体查询
代码语言:javascript复制GET phone/_search
{
"query": {
"match": {
"content": "OS Android Not on"
}
}
}
返回结果和上面一样
为了更直观的显示我们可以使用Search Profiler
进行查询:
可以很直观的看到查询条件被分成了四个字段“OS、Android、Not、on”
测试text类型映射:
代码语言:javascript复制GET phone/_search
{
"query": {
"match": {
"name": "华果"
}
}
}
返回结果:
代码语言:javascript复制{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 4,
"relation" : "eq"
},
"max_score" : 1.0467482,
"hits" : [
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1003",
"_score" : 1.0467482,
"_source" : {
"name" : "华为手机",
"vendor" : "华为",
"pid" : "1003",
"price" : 4488,
"content" : "HarmonyOS Based on Harmony OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1004",
"_score" : 1.0467482,
"_source" : {
"name" : "华为手机",
"vendor" : "华为",
"pid" : "1004",
"price" : 6488,
"content" : "HarmonyOS Not based on Android OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1005",
"_score" : 1.0467482,
"_source" : {
"name" : "苹果手机",
"vendor" : "Apple",
"pid" : "1005",
"price" : 5199,
"content" : "IOS Not based on Android OS",
"area" : "American"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1006",
"_score" : 1.0467482,
"_source" : {
"name" : "苹果手机",
"vendor" : "Apple",
"pid" : "1006",
"price" : 7999,
"content" : "IOS Not based on Harmony OS",
"area" : "American"
}
}
]
}
}
查询字段中的华和果自动被分词了,因此所有name中包含华和果的文档全被检索出来了
同样可以看到关键词被分成了华和果两个字段
测试keyword类型映射:
代码语言:javascript复制GET phone/_search
{
"query": {
"match": {
"vendor": "小华"
}
}
}
返回结果(未查到符合要求文档):
代码语言:javascript复制{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
}
}
代码语言:javascript复制可以看到由于vendor字段被设置了keyword映射,所以查询关键词并没有被分词;所以必须输入该字段的完整值进行查询
GET phone/_search
{
"query": {
"match": {
"vendor": "小米"
}
}
}
返回结果:
代码语言:javascript复制{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.0296195,
"hits" : [
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1001",
"_score" : 1.0296195,
"_source" : {
"name" : "小米手机",
"vendor" : "小米",
"pid" : "1001",
"price" : 3999,
"content" : "MIUI Based on Android OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1002",
"_score" : 1.0296195,
"_source" : {
"name" : "小米手机Pro",
"vendor" : "小米",
"pid" : "1002",
"price" : 4999,
"content" : "MIUI Not based on Harmony OS",
"area" : "China"
}
}
]
}
}
测试index为false(不能被检索):
代码语言:javascript复制GET phone/_search
{
"query": {
"match": {
"pid": "1001"
}
}
}
返回结果:(提示错误信息)
代码语言:javascript复制{
"error" : {
"root_cause" : [
{
"type" : "query_shard_exception",
"reason" : "failed to create query: Cannot search on field [pid] since it is not indexed.",
"index_uuid" : "b4aDx_95SMC49YIjLsLwrw",
"index" : "phone"
}
],
"type" : "search_phase_execution_exception",
"reason" : "all shards failed",
"phase" : "query",
"grouped" : true,
"failed_shards" : [
{
"shard" : 0,
"index" : "phone",
"node" : "a7zlNhivS7iCgDBR91d53Q",
"reason" : {
"type" : "query_shard_exception",
"reason" : "failed to create query: Cannot search on field [pid] since it is not indexed.",
"index_uuid" : "b4aDx_95SMC49YIjLsLwrw",
"index" : "phone",
"caused_by" : {
"type" : "illegal_argument_exception",
"reason" : "Cannot search on field [pid] since it is not indexed."
}
}
}
]
},
"status" : 400
}
字段匹配查询(multi_match)
multi_match 与match 的区别就是它可以在多个字段中进行查询
代码语言:javascript复制GET phone/_search
{
"query": {
"multi_match": {
"query": "华MIUI",
"fields": ["name", "content"]
}
}
}
查询在name和content字段中包含华和MIUI的文档
返回结果:
代码语言:javascript复制{
"took" : 14,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 4,
"relation" : "eq"
},
"max_score" : 1.0816789,
"hits" : [
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1001",
"_score" : 1.0816789,
"_source" : {
"name" : "小米手机",
"vendor" : "小米",
"pid" : "1001",
"price" : 3999,
"content" : "MIUI Based on Android OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1003",
"_score" : 1.0467482,
"_source" : {
"name" : "华为手机",
"vendor" : "华为",
"pid" : "1003",
"price" : 4488,
"content" : "HarmonyOS Based on Harmony OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1004",
"_score" : 1.0467482,
"_source" : {
"name" : "华为手机",
"vendor" : "华为",
"pid" : "1004",
"price" : 6488,
"content" : "HarmonyOS Not based on Android OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1002",
"_score" : 1.0054247,
"_source" : {
"name" : "小米手机Pro",
"vendor" : "小米",
"pid" : "1002",
"price" : 4999,
"content" : "MIUI Not based on Harmony OS",
"area" : "China"
}
}
]
}
}
关键字精确查询(term)
term 查询,精确的关键词匹配查询,不对查询条件进行分词。
代码语言:javascript复制GET phone/_search
{
"query": {
"term": {
"name": {
"value": "小米手机"
}
}
}
}
返回结果:(未查询到)
代码语言:javascript复制{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
}
}
由于text类型默认会被自动分词,所以存入name字段的值:“小米手机”会被自动分成“小、米、手、机”四个字,因此当我们进行精确匹配查询“小米手机”时就会查询不到;只有当查询“小、米、手、机”四个字的任意字时才会匹配到;如果name字段被设为keyword映射,则只有当查询的关键词为“小米手机”时才会进行匹配
多关键字精确查询(terms)
terms查询和term查询的区别是它可以指定多值进行匹配查询,并且只需要匹配一个值即为满足查询条件;类似于mysql 的in 。
代码语言:javascript复制GET phone/_search
{
"query": {
"terms": {
"vendor": ["小米", "华为"]
}
}
}
返回结果:
代码语言:javascript复制{
"took" : 18,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 4,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1001",
"_score" : 1.0,
"_source" : {
"name" : "小米手机",
"vendor" : "小米",
"pid" : "1001",
"price" : 3999,
"content" : "MIUI Based on Android OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1002",
"_score" : 1.0,
"_source" : {
"name" : "小米手机Pro",
"vendor" : "小米",
"pid" : "1002",
"price" : 4999,
"content" : "MIUI Not based on Harmony OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1003",
"_score" : 1.0,
"_source" : {
"name" : "华为手机",
"vendor" : "华为",
"pid" : "1003",
"price" : 4488,
"content" : "HarmonyOS Based on Harmony OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1004",
"_score" : 1.0,
"_source" : {
"name" : "华为手机",
"vendor" : "华为",
"pid" : "1004",
"price" : 6488,
"content" : "HarmonyOS Not based on Android OS",
"area" : "China"
}
}
]
}
}
指定查询字段(_source)
默认情况下,ElasticSearch会将保存在_source中的所有字段都返回。因此我们可以自定义返回的字段
代码语言:javascript复制GET phone/_search
{
"_source": ["name", "area"],
"query": {
"match": {
"name": "小华"
}
}
}
设置_source只返回name和area字段
返回结果:
代码语言:javascript复制{
"took" : 18,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 4,
"relation" : "eq"
},
"max_score" : 1.0467482,
"hits" : [
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1001",
"_score" : 1.0467482,
"_source" : {
"area" : "China",
"name" : "小米手机"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1003",
"_score" : 1.0467482,
"_source" : {
"area" : "China",
"name" : "华为手机"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1004",
"_score" : 1.0467482,
"_source" : {
"area" : "China",
"name" : "华为手机"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1002",
"_score" : 0.9517491,
"_source" : {
"area" : "China",
"name" : "小米手机Pro"
}
}
]
}
}
过滤字段(includes/excludes)
includes:来指定想要显示的字段
excludes:来指定不想要显示的字段 返回结果: boolmustmust_notshould
GET phone/_search
{
"query": {
"bool": {
"must": {
"match": {
"area": "China"
}
},
"must_not": {
"match": {
"content": "abc"
}
},
"should": {
"match": {
"vendor": "华为"
}
}
}
}
}
代码语言:javascript复制{
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 4,
"relation" : "eq"
},
"max_score" : 1.4714522,
"hits" : [
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1003",
"_score" : 1.4714522,
"_source" : {
"name" : "华为手机",
"vendor" : "华为",
"pid" : "1003",
"price" : 4488,
"content" : "HarmonyOS Based on Harmony OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1004",
"_score" : 1.4714522,
"_source" : {
"name" : "华为手机",
"vendor" : "华为",
"pid" : "1004",
"price" : 6488,
"content" : "HarmonyOS Not based on Android OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1001",
"_score" : 0.44183272,
"_source" : {
"name" : "小米手机",
"vendor" : "小米",
"pid" : "1001",
"price" : 3999,
"content" : "MIUI Based on Android OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1002",
"_score" : 0.44183272,
"_source" : {
"name" : "小米手机Pro",
"vendor" : "小米",
"pid" : "1002",
"price" : 4999,
"content" : "MIUI Not based on Harmony OS",
"area" : "China"
}
}
]
}
}
可以看到满足must条件的华为和小米均被查了出来,而符合should要求的华为优先级较高,被排在了前面
范围查询(range)
range 查询找出那些落在指定区间内的数字或者时间。range 查询允许以下字符
操作符 | 说明 |
---|---|
gt | > |
gte | >= |
lt | < |
lte | <= |
GET phone/_search
{
"query": {
"range": {
"price": {
"gte": 4000,
"lte": 5000
}
}
}
}
返回结果:
代码语言:javascript复制{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1002",
"_score" : 1.0,
"_source" : {
"name" : "小米手机Pro",
"vendor" : "小米",
"pid" : "1002",
"price" : 4999,
"content" : "MIUI Not based on Harmony OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1003",
"_score" : 1.0,
"_source" : {
"name" : "华为手机",
"vendor" : "华为",
"pid" : "1003",
"price" : 4488,
"content" : "HarmonyOS Based on Harmony OS",
"area" : "China"
}
}
]
}
}
模糊查询(wildcard)
模糊查询效率较慢,因此不推荐使用;和大部分模糊匹配一样,使用*或者?进行占位替代;
代码语言:javascript复制GET phone/_search
{
"query": {
"wildcard": {
"area": {
"value": "Am*"
}
}
}
}
返回结果:
代码语言:javascript复制{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1005",
"_score" : 1.0,
"_source" : {
"name" : "苹果手机",
"vendor" : "Apple",
"pid" : "1005",
"price" : 5199,
"content" : "IOS Not based on Android OS",
"area" : "American"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1006",
"_score" : 1.0,
"_source" : {
"name" : "苹果手机",
"vendor" : "Apple",
"pid" : "1006",
"price" : 7999,
"content" : "IOS Not based on Harmony OS",
"area" : "American"
}
}
]
}
}
代码语言:javascript复制因为是模糊查询,所以不受keyword映射影响,但是仍然会受到分词器的影响,比如下面实例中的模糊查询name为“小米”的文档,而上面示例已经说了,“小米手机”已经被分词成了四个独立的字,因此通过“小米”去模糊查询,仍然是查询不到的
GET phone/_search
{
"query": {
"wildcard": {
"name": {
"value": "小米"
}
}
}
}
单字段排序(sort)
sort 可以按照不同的字段进行排序,并且通过order 指定排序的方式(desc 降序,asc升序)。
代码语言:javascript复制GET phone/_search
{
"query": {
"match": {"area": "China"}
},
"sort": {
"price": {
"order": "desc"
}
}
}
返回结果:
代码语言:javascript复制{
"took" : 15,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 4,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1004",
"_score" : null,
"_source" : {
"name" : "华为手机",
"vendor" : "华为",
"pid" : "1004",
"price" : 6488,
"content" : "HarmonyOS Not based on Android OS",
"area" : "China"
},
"sort" : [
6488
]
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1002",
"_score" : null,
"_source" : {
"name" : "小米手机Pro",
"vendor" : "小米",
"pid" : "1002",
"price" : 4999,
"content" : "MIUI Not based on Harmony OS",
"area" : "China"
},
"sort" : [
4999
]
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1003",
"_score" : null,
"_source" : {
"name" : "华为手机",
"vendor" : "华为",
"pid" : "1003",
"price" : 4488,
"content" : "HarmonyOS Based on Harmony OS",
"area" : "China"
},
"sort" : [
4488
]
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1001",
"_score" : null,
"_source" : {
"name" : "小米手机",
"vendor" : "小米",
"pid" : "1001",
"price" : 3999,
"content" : "MIUI Based on Android OS",
"area" : "China"
},
"sort" : [
3999
]
}
]
}
}
多字段排序(sort)
为方便测试,添加一个只有ID不同的数据:
代码语言:javascript复制POST /phone/_doc/1007
{
"name":"小米手机Pro",
"vendor":"小米",
"pid":"1007",
"price":4999 ,
"content":"MIUI Not based on Harmony OS",
"area": "China"
}
开始测试:
代码语言:javascript复制GET phone/_search
{
"query": {
"match": {"name": "小米"}
},
"sort": [
{
"price": {
"order": "desc"
}
},
{
"_id": {
"order": "asc"
}
}
]
}
先按价格降序,然后按_id升序
返回结果:
代码语言:javascript复制{
"took" : 18,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1002",
"_score" : null,
"_source" : {
"name" : "小米手机Pro",
"vendor" : "小米",
"pid" : "1002",
"price" : 4999,
"content" : "MIUI Not based on Harmony OS",
"area" : "China"
},
"sort" : [
4999,
"1002"
]
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1007",
"_score" : null,
"_source" : {
"name" : "小米手机Pro",
"vendor" : "小米",
"pid" : "1007",
"price" : 4999,
"content" : "MIUI Not based on Harmony OS",
"area" : "China"
},
"sort" : [
4999,
"1007"
]
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1001",
"_score" : null,
"_source" : {
"name" : "小米手机",
"vendor" : "小米",
"pid" : "1001",
"price" : 3999,
"content" : "MIUI Based on Android OS",
"area" : "China"
},
"sort" : [
3999,
"1001"
]
}
]
}
}
测试完成后,删除刚刚添加的数据
高亮查询(highlight)
Elasticsearch 可以对查询内容中的关键字部分,进行标签和样式(高亮)的设置。 在使用match 查询的同时,加上一个highlight 属性(可以不设置,不设置则为默认值):
pre_tags:前置标签 (默认为em标签)
post_tags:后置标签 (默认为em标签)
fields:需要高亮的字段
title:这里声明title 字段需要高亮,后面可以为这个字段设置特有配置
返回结果:
代码语言:javascript复制{
"took" : 6,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.699713,
"hits" : [
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1001",
"_score" : 1.699713,
"_source" : {
"name" : "小米手机",
"vendor" : "小米",
"pid" : "1001",
"price" : 3999,
"content" : "MIUI Based on Android OS",
"area" : "China"
},
"highlight" : {
"name" : [
"<font color='red'>小</font><font color='red'>米</font>手机"
]
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1002",
"_score" : 1.5478239,
"_source" : {
"name" : "小米手机Pro",
"vendor" : "小米",
"pid" : "1002",
"price" : 4999,
"content" : "MIUI Not based on Harmony OS",
"area" : "China"
},
"highlight" : {
"name" : [
"<font color='red'>小</font><font color='red'>米</font>手机Pro"
]
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1007",
"_score" : 1.5478239,
"_source" : {
"name" : "小米手机Pro",
"vendor" : "小米",
"pid" : "1007",
"price" : 4999,
"content" : "MIUI Not based on Harmony OS",
"area" : "China"
},
"highlight" : {
"name" : [
"<font color='red'>小</font><font color='red'>米</font>手机Pro"
]
}
}
]
}
}
因为是html语法,所以返回结果里面只有文字,而不是直接显示效果
分页查询(from)
from:当前页的起始索引,默认从0 开始。 from = (页数 - 1) * size 【即from为0时,为第一页,以此类推】 size:每页显示多少条
代码语言:javascript复制GET phone/_search
{
"query": {
"match_all": {}
},
"sort": {
"price": {
"order": "asc"
}
},
"from": 0,
"size": 2
}
返回结果:
代码语言:javascript复制{
"took" : 10,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 7,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1001",
"_score" : null,
"_source" : {
"name" : "小米手机",
"vendor" : "小米",
"pid" : "1001",
"price" : 3999,
"content" : "MIUI Based on Android OS",
"area" : "China"
},
"sort" : [
3999
]
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1003",
"_score" : null,
"_source" : {
"name" : "华为手机",
"vendor" : "华为",
"pid" : "1003",
"price" : 4488,
"content" : "HarmonyOS Based on Harmony OS",
"area" : "China"
},
"sort" : [
4488
]
}
]
}
}
聚合查询(aggs)
聚合允许使用者对es文档进行统计分析,类似与MySQL中的group by
度量聚合
例如取最大值(max)、最小值(min)、平均值(avg)、总数(count)、 去重后求总数(cardinality)、返回所有度量类型的统计(stats)等等。
代码语言:javascript复制GET phone/_search
{
"aggs": { //aggs表示聚合操作
"sum_price": { //sum_price为自定义的分组名
"sum": { //sum表示求和
"field": "price" //分组字段:price
}
}
}
}
返回结果:
代码语言:javascript复制{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 6,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1001",
"_score" : 1.0,
"_source" : {
"name" : "小米手机",
"vendor" : "小米",
"pid" : "1001",
"price" : 3999,
"content" : "MIUI Based on Android OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1002",
"_score" : 1.0,
"_source" : {
"name" : "小米手机Pro",
"vendor" : "小米",
"pid" : "1002",
"price" : 4999,
"content" : "MIUI Not based on Harmony OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1003",
"_score" : 1.0,
"_source" : {
"name" : "华为手机",
"vendor" : "华为",
"pid" : "1003",
"price" : 4488,
"content" : "HarmonyOS Based on Harmony OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1004",
"_score" : 1.0,
"_source" : {
"name" : "华为手机",
"vendor" : "华为",
"pid" : "1004",
"price" : 6488,
"content" : "HarmonyOS Not based on Android OS",
"area" : "China"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1005",
"_score" : 1.0,
"_source" : {
"name" : "苹果手机",
"vendor" : "Apple",
"pid" : "1005",
"price" : 5199,
"content" : "IOS Not based on Android OS",
"area" : "American"
}
},
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "1006",
"_score" : 1.0,
"_source" : {
"name" : "苹果手机",
"vendor" : "Apple",
"pid" : "1006",
"price" : 7999,
"content" : "IOS Not based on Harmony OS",
"area" : "American"
}
}
]
},
"aggregations" : {
"max_price" : {
"value" : 33172.0
}
}
}
在查询结果底部的aggregations字段中可以看到得到的相加结果为33172.0
桶聚合查询
在已有的分组条件下再进行聚合即为桶聚合,相当于MySQL中的group by 语句;桶聚合返回很多子集,并限定输入数据到一个特殊的叫做桶的子集中。可以把桶聚合想象成 类似切面功能的东西。
- term聚合:词条的聚合
terms聚合为字段中每个词条返回一个桶。允许你生成字段每个值的统计;
- range聚合和date range聚合
范围聚合和时间范围聚合
- 桶嵌套
多个聚合的嵌套即为桶嵌套
后记
- Elasticsearch 是使用 java 开发的,7.8 版本及以上需要 JDK 版本 1.8 以上,默认安装包带有 jdk 环境,如果系统配置了JDK环境变量,会默认使用系统配置的 JDK,如果没有配置使用自带的 JDK,一般建议使用系统配置的 JDK。
- 双击启动窗口闪退,通过路径访问追踪错误,如果是“空间不足”,可以尝试修改config/jvm.options 配置文件
# 设置 JVM 初始内存为 1G。此值可以设置与-Xmx 相同,以避免每次垃圾回收完成后 JVM 重新分配内存 # Xms represents the initial size of total heap space # 设置 JVM 最大可用内存为 1G # Xmx represents the maximum size of total heap space
-Xms1g
-Xmx1g
中文支持
在Kiabana的配置文件中修改,然后重启Kiabana即可:
代码语言:javascript复制# Specifies locale to be used for all localizable strings, dates and number formats.
# Supported languages are the following: English - en , by default , Chinese - zh-CN .
i18n.locale: "zh-CN"
可视化操作
直接对索引操作:
文档的可视化操作
首先在左侧菜单进入Stack Management,然后选择索引模式新建一个索引模式,首次会进行引导
创建完成后,可以点击创建的索引进入详情页,进行操作,也可以直接在右上角创建索引模式继续创建索引
然后在左侧菜单选择Discover,就可以对文档进行可视化操作了