1 - 基于ELK的ElasticSearch 7.8.x 技术整理 - 基础语法篇 - 更新完毕
发布于 2022年 01月 12日 11:26
准备工作
0、什么是ElasticSearch?它和Lucene以及solr的关系是什么?
这些是自己的知识获取能力,自行百度百科
1、下载ElasticSearch的window版,linux版后续说明
自行百度Elastic,然后进到官网进行下载,我的版本是:7.8.0
2、下载postman
自行百度进行下载
3、ElasticSearch中的目录解读( 会tomcat,看到这些目录就不陌生 )
进到bin目录下,点击 elasticsearch.bat 文件即可启动 ES 服务
4、ELK技术是什么意思?
- 就图中这三个
5、注意事项
- 保证自己的JDK是1.8或以上,最低要求1.8
0、ES非关系型和关系型数据库对应关系
注意:ES 7.x之后,type已经被淘汰了,其他的没变
只要玩ES,那么这个图就要牢牢地记在自己脑海里,后续的名词解释不再过多说明,就是操作这幅图中的东西
1、索引
-
这里需要解释一个东西:倒排索引
-
解释之前先来对照关系型数据库看一下:正排索引
1.1、创建索引
语法:
http://ip:port/index_name 如:http://127.0.0.1:9200/create_index 请求方式:put
注:put请求具有幂等性
- 指的是: 不管进行多少次重复操作,都是实现相同的结果。可以采用把下面的请求多执行几次,然后:观察返回的结果
还具有幂等性的有:put、delete、get
1.1、获取索引
语法:
http://ip:port/index_name 如:http://127.0.0.1:9200/create_index 请求方式:get
1.3、获取ES中的全部索引
http://ip:port/_cat/indices?v 如:http://127.0.0.1:9200/_cat/indices?v
1.4、删除索引
语法:
http://ip:port/index_name 如:http://127.0.0.1:9200/create_index 注意:请求方式为delete
2、文档_doc
2.1、使用post创建doc
这种方式:是采用ES随机生成id时使用的请求方式
注:需要先创建索引,因为:这就类似于关系型数据库中在数据库的表中 创建数据
语法:
http://ip:port/index_name/_doc 如: http://127.0.0.1:9200/create_index/_doc 请求方式:post
2.2、使用put创建doc - 转幂等性 - 自定义id
在路径后面加一个要创建的id值即可
2.3、查询文档_doc - 重点
2.3.1、id查询单条_doc
语法:
http://ip:port/index_name/_doc/id 如: http://127.0.0.1:9200/create_index/_doc/100001 请求方式:get
2.3.2、查询ES中索引下的全部_doc
语法:
http://ip:port/index_name/_search 如: http://127.0.0.1:9200/create_index/_search 请求方式:get
注意:别再body中携带数据了,不然就会报:
Unknown key for a VALUE_STRING in [title]
返回的结果:
点击查看代码
{ "took": 69, 查询花费的时间 毫秒值 "timed_out": false, 是否超时 "_shards": { 分片 还没学,先不看 "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 3, "relation": "eq" }, "max_score": 1.0, "hits": [ 查询出来的 当前索引下的所有_doc文档 { "_index": "create_index", "_type": "_doc", "_id": "Pdy1sX0B_g8Hput6sCw6", "_score": 1.0, "_source": { "title": "这是第一次学习ES的表数据创建", "author": "紫邪情", "sex": "girl" } }, { "_index": "create_index", "_type": "_doc", "_id": "Pty5sX0B_g8Hput6eyzA", "_score": 1.0, "_source": { "title": "这是第一次学习ES的表数据创建", "author": "紫邪情", "sex": "girl" } }, { "_index": "create_index", "_type": "_doc", "_id": "100001", "_score": 1.0, "_source": { "title": "这是第一次学习ES的表数据创建", "author": "紫邪情", "sex": "girl" } } ] } }
2.4、文档_doc的修改
2.4.1、全量修改
原理:利用内容覆盖,重新发一份文档罢了
语法:
http://ip:port/index_name/_doc/id 如: http://127.0.0.1:9200/create_index/_doc/100001 请求方式:post
获取_doc文档,检验一下
2.4.2、局部修改
语法:
http://ip:port/index_name/_update/id 如: http://127.0.0.1:9200/create_index/_update/100001 请求方式:post
检验一下:
2.5、文档_doc的删除
使用delete请求即可
2.6、条件查询 - 重点
2.6.1、url携带条件
语法:
http://ip:port/index_name/_search?q=条件字段:值 如: http://127.0.0.1:9200/create_index/_search?q=author:邪 请求方式:get
注:这种方式不建议用,了解即可吧
- 返回的结果体:
点击查看代码
{ "took": 26, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 2, "relation": "eq" }, "max_score": 0.18232156, "hits": [ { "_index": "create_index", "_type": "_doc", "_id": "Pdy1sX0B_g8Hput6sCw6", "_score": 0.18232156, "_source": { "title": "这是第一次学习ES的表数据创建", "author": "紫邪情", "sex": "girl" } }, { "_index": "create_index", "_type": "_doc", "_id": "Pty5sX0B_g8Hput6eyzA", "_score": 0.18232156, "_source": { "title": "这是第一次学习ES的表数据创建", "author": "紫邪情", "sex": "girl" } } ] } }
2.6.2、请求体携带条件 - 推荐使用的一种
语法:
http://ip:port/index_name/_search 如: http://127.0.0.1:9200/create_index/_search 请求方式:get
请求体携带的数据:
点击查看代码
{ "query": { "match":{ match 匹配、配对 "author": "邪" 条件 } } }
结果返回:
点击查看代码
{ "took": 3, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 2, "relation": "eq" }, "max_score": 0.18232156, "hits": [ { "_index": "create_index", "_type": "_doc", "_id": "Pdy1sX0B_g8Hput6sCw6", "_score": 0.18232156, "_source": { "title": "这是第一次学习ES的表数据创建", "author": "紫邪情", "sex": "girl" } }, { "_index": "create_index", "_type": "_doc", "_id": "Pty5sX0B_g8Hput6eyzA", "_score": 0.18232156, "_source": { "title": "这是第一次学习ES的表数据创建", "author": "紫邪情", "sex": "girl" } } ] } }
2.7、分页查询 - 重点
语法:
http://ip:port/index_name/_search 如: http://127.0.0.1:9200/create_index/_search 请求方式:get
请求体内容:
点击查看代码
{ "query":{ "match_all":{} 注意:这里使用的是match_all }, "from": 0, 相当于:startNum 这个数字的算法:(当前页码-1)*要显示的条数 "size": 1 相当于:pageSize }
返回结果:
点击查看代码
{ "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": "create_index", "_type": "_doc", "_id": "Pdy1sX0B_g8Hput6sCw6", "_score": 1.0, "_source": { "title": "这是第一次学习ES的表数据创建", "author": "紫邪情", "sex": "girl" } } ] } }
2.8、排序查询 - 重点
语法:
http://ip:port/index_name/_search 如: http://127.0.0.1:9200/create_index/_search 请求方式:get
请求体内容:
点击查看代码
{ "query":{ "match_all":{} }, "sort":{ 排序 "_id":{ 根据什么字段排序 "order":"desc" 排序方式 desc降序 asc升序 } } }
返回结果:
点击查看代码
{ "took": 49, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 2, "relation": "eq" }, "max_score": null, "hits": [ { "_index": "create_index", "_type": "_doc", "_id": "Pty5sX0B_g8Hput6eyzA", "_score": null, "_source": { "title": "这是第一次学习ES的表数据创建", "author": "紫邪情", "sex": "girl" }, "sort": [ "Pty5sX0B_g8Hput6eyzA" ] }, { "_index": "create_index", "_type": "_doc", "_id": "Pdy1sX0B_g8Hput6sCw6", "_score": null, "_source": { "title": "这是第一次学习ES的表数据创建", "author": "紫邪情", "sex": "girl" }, "sort": [ "Pdy1sX0B_g8Hput6sCw6" ] } ] } }
2.9、多条件查询 - 重点
2.9.1、and查询
语法:
http://ip:port/index_name/_search 如: http://127.0.0.1:9200/create_index/_search 请求方式:get
请求体内容:
点击查看代码
{ "query":{ "bool":{ "must":[ 就相当于是mysql中的 and拼接条件 { "match":{ and条件1 "author":"邪" } },{ "match":{ and条件2 "_id":"Pdy1sX0B_g8Hput6sCw6" } } ] } } }
返回结果:
点击查看代码
{ "took": 2, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 1, "relation": "eq" }, "max_score": 1.1823215, "hits": [ { "_index": "create_index", "_type": "_doc", "_id": "Pdy1sX0B_g8Hput6sCw6", "_score": 1.1823215, "_source": { "title": "这是第一次学习ES的表数据创建", "author": "紫邪情", "sex": "girl" } } ] } }
2.9.2、or查询
语法:
http://ip:port/index_name/_search 如: http://127.0.0.1:9200/create_index/_search 请求方式:get
请求体内容:
点击查看代码
{ "query":{ "bool":{ "should":[ 对照must,改变的地方 { "match":{ "author":"邪" } },{ "match":{ "_id":"Pdy1sX0B_g8Hput6sCw6" } } ] } } }
返回的结果:
点击查看代码
{ "took": 2, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 2, "relation": "eq" }, "max_score": 1.1823215, "hits": [ { "_index": "create_index", "_type": "_doc", "_id": "Pdy1sX0B_g8Hput6sCw6", "_score": 1.1823215, "_source": { "title": "这是第一次学习ES的表数据创建", "author": "紫邪情", "sex": "girl" } }, { "_index": "create_index", "_type": "_doc", "_id": "Pty5sX0B_g8Hput6eyzA", "_score": 0.18232156, "_source": { "title": "这是第一次学习ES的表数据创建", "author": "紫邪情", "sex": "girl" } } ] } }
2.10、范围查询 - 重点
语法:
http://ip:port/index_name/_search 如: http://127.0.0.1:9200/create_index/_search 请求方式:get
请求体内容:
点击查看代码
{ "query":{ "bool":{ "should":[ { "match":{ "author":"邪" } },{ "match":{ "title":"一" } } ], "filter":{ 就多了这么一个filter range而已 "range":{ "id":{ "gt":1000 gt > lt < 在html中见过滴 } } } } } }
返回结果:下面的两条数据是我重新加的
点击查看代码
{ "took": 34, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 2, "relation": "eq" }, "max_score": 0.0, "hits": [ { "_index": "create_index", "_type": "_doc", "_id": "Vtz2sn0B_g8Hput64ywM", "_score": 0.0, "_source": { "id": 10001, "title": "大王叫我来巡山", "author": "王二麻子" } }, { "_index": "create_index", "_type": "_doc", "_id": "V9z5sn0B_g8Hput6HyyQ", "_score": 0.0, "_source": { "id": 10002, "title": "论皮包龙是怎么形成的", "author": "波多野结衣" } } ] } }
2.11、完全匹配 - 精准匹配 - 重点
-
在玩这个之前可以回到前面看一下我前面例子中的:条件查询
-
在那里,老衲做的有一个操作:只用了一个字符:邪,但是:最后得到了想要的结果
-
上面这种:叫做全文检索,它是去:我创建的create_index索引下的找寻所有的内容,从而匹配出:author包含“邪”的内容,如果此时自己定的条件是:多个字符的话,那么:底层是把这些字符拆成单个字符了,从而匹配出来的
-
而所谓的完全匹配:就是精准匹配到某条数据,它虽然也会拆成单个字符,但是:查询时,还是整串字符绑定在一起匹配的
- 如:查询"紫邪情",用全文检索就是:紫、邪、情,单独匹配,从而判定,如果此时:使用"紫邪晴",那么:也会匹配到
- 但是:如果使用的是完全匹配"紫邪晴",虽然也会拆分为:紫、邪、晴,可是:它最后去匹配结果时,是使用"紫邪晴"这整个字符串来比对的,所以:最后结果不会匹配到
语法:
http://ip:port/index_name/_search 如: http://127.0.0.1:9200/create_index/_search 请求方式:get
全文检索和完全匹配对比
2.12、高亮查询
语法:
http://ip:port/index_name/_search 如: http://127.0.0.1:9200/create_index/_search 请求方式:get
请求体内容:
点击查看代码
{ "query":{ "match":{ "author":"紫邪情" } }, "highlight":{ 高亮 "fields":{ 哪个字段需要高亮 "author":{} } } }
返回结果:
点击查看代码
{ "took": 59, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 2, "relation": "eq" }, "max_score": 2.264738, "hits": [ { "_index": "create_index", "_type": "_doc", "_id": "Pdy1sX0B_g8Hput6sCw6", "_score": 2.264738, "_source": { "title": "这是第一次学习ES的表数据创建", "author": "紫邪情", "sex": "girl" }, "highlight": { "author": [ "<em>紫</em><em>邪</em><em>情</em>" ] } }, { "_index": "create_index", "_type": "_doc", "_id": "Pty5sX0B_g8Hput6eyzA", "_score": 2.264738, "_source": { "title": "这是第一次学习ES的表数据创建", "author": "紫邪情", "sex": "girl" }, "highlight": { "author": [ "<em>紫</em><em>邪</em><em>情</em>" ] } } ] } }
2.13、组合查询
2.13.1、分组
语法:
http://ip:port/index_name/_search 如: http://127.0.0.1:9200/create_index/_search 请求方式:get
请求体内容:
点击查看代码
{ "aggs": { // 组合操作标识 "author_group": { // 分组之后的名称 随便取 "terms": { // 分组标识 "field": "id" // 注意:这里分组别用字符串类型的字段,如:author } } }, "size": 0 // 设定不显示原始数据,否则:"hits":{}这个原始数据也会暴露出来 }
加上size之后的返回结果:
点击查看代码
{ "took": 5, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 4, "relation": "eq" }, "max_score": null, "hits": [] // 这里的hits就被去掉了 }, "aggregations": { "author_group": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": 10001, "doc_count": 1 }, { "key": 10002, "doc_count": 1 } ] } } }
2.13.2、平均数
语法:
http://ip:port/index_name/_search 如: http://127.0.0.1:9200/create_index/_search 请求方式:get
请求体内容:
点击查看代码
{ "aggs":{ "id_avg":{ "avg":{ "field":"id" } } }, "size":0 }
返回结果:
点击查看代码
{ "took": 4, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 4, "relation": "eq" }, "max_score": null, "hits": [] }, "aggregations": { "id_avg": { "value": 10001.5 } } }
同样的道理:sum总和之类的也可以写的,把标识改为对应的函数名字、field字段即可
2.14、映射关系
- 就相当于:在做mysql数据库中的表结构( 字段构建嘛:字段名、类型... )
2.14.1、建立索引
点击查看代码
http:127.0.0.1:9200/user // 请求类型:put
2.14.2、建立映射关系
点击查看代码
http://127.0.0.1:9200/user/_mapping // 请求方式:put // 请求体内容 { "properties":{ "name":{ "type":"text", "index":true }, "age":{ "type":"keyword", "index":false }, "address":{ "type":"keyword", "index":true } } } // 2、查看映射关系 http://127.0.0.1:9200/user/_mapping // 请求方式:get // 3、添加数据 http://127.0.0.1:9200/user/_doc // 请求方式 post // 请求体内容 { "name":"紫邪情", "sex":"女滴", "age":18, "address":"地球村" } // 4、查看数据 http://127.0.0.1:9200/user/_search // 请求方式 post
2.14.3、测试
点击查看代码
http://127.0.0.1:9200/user/_search // 请求方式 get // 请求体内容 { "query":{ "bool":{ "must":[ { "match":{ "name":"邪" } },{ "match":{ "age":18 } },{ "match":{ "address":"地球村" } } ] } } }
返回结果:
点击查看代码
{ "error": { "root_cause": [ { "type": "query_shard_exception", "reason": "failed to create query: Cannot search on field [age] since it is not indexed.", // 重点信息在这里,但是:现在先不解答这个错误的原因,继续测试 "index_uuid": "To8O7VKkR3OM_drdWZQIIA", "index": "user" } ], "type": "search_phase_execution_exception", "reason": "all shards failed", "phase": "query", "grouped": true, "failed_shards": [ { "shard": 0, "index": "user", "node": "w6AVu2CHT6OEaXAJmqT8mw", "reason": { "type": "query_shard_exception", "reason": "failed to create query: Cannot search on field [age] since it is not indexed.", "index_uuid": "To8O7VKkR3OM_drdWZQIIA", "index": "user", "caused_by": { "type": "illegal_argument_exception", "reason": "Cannot search on field [age] since it is not indexed." } } } ] }, "status": 400 }
上面说:age不允许被index( 检索 ) , 那么删掉它,再看效果
请求体变为如下:
点击查看代码
{ "query":{ "bool":{ "must":[ { "match":{ "name":"邪" } },{ // 去掉了age属性 "match":{ "address":"地球村" } } ] } } }
发现能够获取到结果
再变一下:
现在回到前面报的错:failed to create query: Cannot search on field [age] since it is not indexed
- 为什么报这个错?其实已经告知得很清楚了:field [age] since it is not indexed 属性age不支持被检索,原因:
为什么前面使用"地球村"可以查到数据,而使用"地球"就不可以查到?
2.15.5、text和keyword类型的区别
-
text类型支持全文检索和完全查询,即:我搜索时只用字符串中的一个字符照样得到结果
- 原理:text使用了分词,就是把字符串拆分为单个字符串了
-
keyword类型支持完全查询,即:精确查询,前提:index不是false
- 原理:keyword不支持分词,所以:查询时必须是完全查询( 所有字符匹配上才可以 )
3、 java操作篇链接
作者:紫邪情
欢迎任何形式的转载,但请务必注明出处。
限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。