elasticsearch是一个分布式的全文搜索引擎。
基于Lucene。具有restful的api接口。分布式,高横向扩展能力。
全文检索:分词,在分词库想分词后的关键词。倒排索引。
与solr的区别
效率:
单纯的对已有数据进行检索的时候,solr效率更好,高于es;在不断动态添加数据的时候,solr的检索效率会变的低下,而es则没有什么变化。
独立性:
Solr利用zookeeper进行分布式管理,而es自身带有分布式系统管理功能。
倒排索引也叫反向索引,通俗来讲正向索引是通过key找value,反向索引则是通过value找key。
type在7中已经被遗弃,ES官方建议 在一个索引库中只存储相同类型的文档。
ik分词器
可以去GitHub下载,但是网络问题,可以进入容器,然后切到目录 /usr/share/elasticsearch/bin。之后可以执行./elasticsearch-plugin install http://tomcat01.qfjava.cn:81/elasticsearch-analysis-ik-6.5.4.zip。最后重启一下。
POST _analyze
{
"analyzer": "ik_max_word",
"text": "中国湖北"
}
# 分为了[中国]和[湖北]
field字段类型,常见如下
字符串类型
text 、 keyword
数值类型
long, integer, short, byte, double, float, half_float, scaled_float
日期类型
date
布尔值类型
boolean
二进制类型
binary
范围类型
integer_range, float_range, long_range, double_range, date_range
操作es的restful语法。原本的put修改,post新增,get查询,delete删除
Get:查询
# 查询索引信息
http://ip:port/index
# 查询文档信息
http://ip:port/index/type/doc_id
Post:查询
# 查询(查询参数太多的情况,参数可以json格式传参)
http://ip:port/index/type/_search
# 更新
http://ip:port/index/type/doc_id/_update
#创建一个文档(一条数据)
http://ip:port/index/type/doc
Put:创建索引
# 创建一个索引,请求体中指定数据结构(即type和字段,settings和mappings)
http://ip:port/index
# 创建一个文档的属性有哪些,请求体中指定具体信息
http://ip:port/index/type/_mappings
#创建一个文档(一条数据)
http://ip:port/index/type/doc
Delete:删
# 删除一个索引,对应的数据全部被删除了
http://ip:port/index
# 删除一个文档
http://ip:port/index/type/doc_id
具体操作
3.1 索引操作
创建一个索引
# 简单创建一个索引,默认副本数为1,分片数为5
PUT /qsm
# 简单创建一个索引,指定副本数和分片数
PUT /qsm1
{
"settings": {
"number_of_shards": 5
, "number_of_replicas": 1
}
}
# 若已创建索引,给索引添加数据结构
PUT /qsm/novel/_mappings
{
"properties":{
"name":{
"type":"text"
},
"author":{
"type":"keyword"
},
"count":{
"type":"long"
},
"onSale":{
"type":"date",
"format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
}
# 创建一个索引并制定数据结构
PUT /book
{
"settings": {
"number_of_shards": 5
, "number_of_replicas": 1
},
"mappings": {
"novel":{
"properties":{
"name":{
"type":"text",
"analyzer":"ik_max_word"
},
"author":{
"type":"keyword"
},
"count":{
"type":"long"
},
"onSale":{
"type":"date",
"format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
}
}
}
删除索引
# 删除某一个索引
DELETE /qsm
# 删除某个前缀的所有索引
DELETE /qsm*
查看索引信息
# 查看某个索引
GET /qsm1
# 查看所有索引列表
GET /_cat/indices?v
3.2 文档操作
创建文档
# 自动创建文档id
POST /book/novel
{
"name":"大秦帝国",
"author":"qsm",
"count":"10",
"onSale":"2020-07-21"
}
# 手动创建文档id
POST /book/novel/1
{
"name":"大清帝国",
"author":"qsm",
"count":"20",
"onSale":"2020-07-11"
}
更改文档
# 覆盖修改,直接相当于已知文档id的手动创建
POST /book/novel/1
{
"name":"大清帝国_copy",
"author":"qsm",
"onSale":"2020-07-11"
}
# 制定修改,基于doc
POST /book/novel/1/_update
{
"doc": {
"name":"大清帝国_copy2"
}
}
删除文档
DELETE /book/novel/qk4vcHMBO6OsUd5sLTc
查询文档
GET /book/novel/1
深分页
ES对from和size之和有限制,不能大于1w
from+size原理:
根据用户输入的词语进行分词
将分词后的分词去分词库中进行检索,得到文档的id
去各个分片中拉去指定的数据
根据数据的score分数进行排序
根据from/limit进行筛选出指定的数据,其他数据舍弃
返回结果
scroll+size原理:
根据用户输入的词语进行分词
将分词后的分词去分词库中进行检索,得到文档的id
将文档的id【放入到一个es上下文中】
根据指定的size去各个分片中拉去指定的数据,并且拿完的文档id会被上下文移除
若需要下一页size的数据,则去es上下文中拿到文档id
接下来跟第四步一样,进行循环
所以scroll没有分数,且不适合实时查询。但是非常快,资源消耗少。
指定scroll查询的时候,会给这个上下文指定过期时间(可以保持)。排序默认是id,也可以手动自定
# from+size
POST /sms-logs-index/sms-logs-type/_search
{
"from": 0,
"size": 2,
"query": {
"wildcard": {
"smsContent": {
"value": "*荆楚"
}
}
}
}
# 指定scroll查询
POST /sms-logs-index/sms-logs-type/_search?scroll=2m
{
"size": 2 ,
"query": {
"match": {
"smsContent": "荆楚"
}
},
"sort": [
{
"fee": {
"order": "desc"
}
}
]
}
#得到数据中"_scroll_id" : "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAA0yFndERmlrTURiUk42NVlhdS1sTElqTlEAAAAAAAANMxZ3REZpa01EYlJONjVZYXUtbExJak5RAAAAAAAADTQWd0RGaWtNRGJSTjY1WWF1LWxMSWpOUQAAAAAAAA02FndERmlrTURiUk42NVlhdS1sTElqTlEAAAAAAAANNRZ3REZpa01EYlJONjVZYXUtbExJak5R"
# scroll下一页查询
POST /_search/scroll
{
"scroll_id":"DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAA0yFndERmlrTURiUk42NVlhdS1sTElqTlEAAAAAAAANMxZ3REZpa01EYlJONjVZYXUtbExJak5RAAAAAAAADTQWd0RGaWtNRGJSTjY1WWF1LWxMSWpOUQAAAAAAAA02FndERmlrTURiUk42NVlhdS1sTElqTlEAAAAAAAANNRZ3REZpa01EYlJONjVZYXUtbExJak5R",
"scroll":"2m"
}
# 删除scroll
DELETE /_search/scroll/DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAA4_FndERmlrTURiUk42NVlhdS1sTElqTlEAAAAAAAAOQRZ3REZpa01EYlJONjVZYXUtbExJak5RAAAAAAAADkAWd0RGaWtNRGJSTjY1WWF1LWxMSWpOUQAAAAAAAA5CFndERmlrTURiUk42NVlhdS1sTElqTlEAAAAAAAAOQxZ3REZpa01EYlJONjVZYXUtbExJak5R
查询的基本知识:
若想查询短信信息字段中包含“中国湖北”的数据。则ik分词器会"中国湖北"分为“中国湖北”,“中国”,“湖北”,那么有这三个字段的文档都会匹配查询到,但是会有一个分数,分数最高则会最优质匹配。
前提数据准备
创建索引
PUT /sms-logs-index
{
"settings": {
"number_of_replicas": 1,
"number_of_shards": 5
},
"mappings": {
"sms-logs-type":{
"properties":{
"corpName":{
"type":"keyword"
},
"smsContent":{
"type":"text",
"analyzer":"ik_max_word"
},
"fee":{
"type":"long"
},
"province":{
"type":"keyword"
},
"create":{
"type":"date",
"format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
}
}
}
导入数据,可以自己随便编写数据。编写10条左右即可
POST /sms-logs-index/sms-logs-type
{
"corpName":"中国联通",
"smsContent":"欢迎您来到齐鲁大地,祝您平安愉快!拨打漫游地区号+12580订票订房;办理移动业务,请拨10086咨询;中国联通山东公司将竭诚为您服务。",
"fee":"30",
"province":"山东",
"create":"2020-05-19"
}
match_all查询
查询所有,相当于没有任何查询条件。默认size为10
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"match_all": {}
}
}
match查询
高级查询,不同字段类型采用不同的查询方式
日期或者数字,自动转
keyword,不会分词
text,会自动分词
# match查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"match": {
"smsContent": "中国电信"
}
}
}
# 注意:中国电信会被分词为:中国移动、中国移、中国、移动。所以只要文档的smsContent字段内容包含了这四个词的,都会被查出来,仅仅是分数会低一下,比如有的内容只出现了[中国]
# 现在更新为"smsContent": "齐鲁",则展示结果如下
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 1.2005384,
"hits" : [
{
"_index" : "sms-logs-index",
"_type" : "sms-logs-type",
"_id" : "PLNYcHMB9IjDRQti4nhj",
"_score" : 1.2005384,
"_source" : {
"corpName" : "中国联通",
"smsContent" : "欢迎您来到齐鲁大地,祝您平安愉快!拨打漫游地区号+12580订票订房;办理移动业务,请拨10086咨询;中国联通山东公司将竭诚为您服务。",
"fee" : "30",
"province" : "山东",
"create" : "2020-05-19"
}
}
]
}
}
# 布尔match查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"match": {
"smsContent": {
"query": "齐鲁 大地",
"operator": "or"
}
}
}
}
mutil_match查询
之前是针对一个field的内容做value检索,mutil_match则是针对多个filed中对该value做检索
#mutil_match查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"multi_match": {
"query": "中国热线",
"fields": ["corpName","smsContent"]
}
}
}
# 中国热线,在corpName不会被分词,在smsContent会被分词
term查询
代表完全匹配。不会分词,直接去分词库中匹配内容,所以很适合string文本类型为keyword类型的。
以“奋斗的时代”为例:使用ik分词器分为:奋斗,奋,斗,时代。但是term和terms是不分词的,所以ik分词器中是没有“奋斗的时代”这5个字的词语,所以就查询不到。即使后面正在的完整句子有改5个字的词语。
POST /sms-logs-index/sms-logs-type/_search
{
"from": 0,
"size": 20,
"query": {
"term": {
"corpName": {
"value": "中国移动"
}
}
}
}
terms查询
机制跟term一致,不过它可以针对一个field字段的内容包含多个值的时候使用。如同sql中or。省份为北京或者上海或者辽宁
POST /sms-logs-index/sms-logs-type/_search
{
"from": 0,
"size": 20,
"query": {
"terms": {
"province": [
"辽宁",
"山东"
]
}
}
}
id查询
直接根据文档的id获取某一条数据
GET /sms-logs-index/sms-logs-type/PrNjcHMB9IjDRQtiY3hb
ids查询
根据多个id获取
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"ids": {
"values": ["NrNWcHMB9IjDRQtiK3iX","PrNjcHMB9IjDRQtiY3hb"]
}
}
}
fuzzy模糊纠正查询
根据查询词语,大概的去查询数据。注意是大概,也就是很不稳定,因为查询词语可以是有错别字等。比如,想去匹配盒马鲜生,输入河马先生也是有可能查询的到。但是差距太大,则也有可能差不多。所以稳定性差
# 改为中国一动可以查询的到,但是改为中国yi动则查询不到
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"fuzzy": {
"corpName": {
"value": "中国一动"
}
}
}
}
# 前面3个字符一样,这样的话就查询不到了
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"fuzzy": {
"corpName": {
"value": "中国一动",
"prefix_length": 3
}
}
}
}
prefix前缀查询
可以根据想搜索字段的前面的一部分去搜索。不仅仅适合text类型,也适用于keyword关键字类型的。都能查出
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"prefix": {
"smsContent": {
"value": "尊敬"
}
}
}
}
wildcard通配查询
跟mysql的like查询类似。通配符*为多个未知字符,?为一个字符。
非常消耗资源
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"wildcard": {
"corpName": {
"value": "??电信"
}
}
}
}
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"wildcard": {
"smsContent": {
"value": "*荆楚"
}
}
}
}
regexp正则查询
正则匹配的查询
以上fuzzy、prefix、wildcard和regexp查询效率低,耗费资源的。前缀匹配是优于wildcard和regexp。
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"regexp": {
"corpName": "中国联通[0-9]{2}"
}
}
}
# 有一个数据 "corpName" : "中国联通12"。所以该正则可以查到数据
rang数字范围查询
范文查询,针对数字
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"range": {
"fee": {
"gte": 100,
"lte": 200
}
}
}
}
delete_by_query
根据match或者term等基本查询操作查询到的数据进行删除
POST /sms-logs-index/sms-logs-type/_delete_by_query
{
"query":{
"range":{
"fee":{
"gte": 3000
}
}
}
}
# 结果如下deleted为2,删除了2条
{
"took" : 32,
"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" : [ ]
}
bool查询
过滤器查询,将多个查询调教,以一定逻辑操作组合到一起
must:相当于都符合,and
must_not:相当于都不符合,not
should:相当于或者,or
filter:不计算分数,对经常过滤的数据进行缓存
# 省份为湖北或者北京
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"bool": {
"should": [
{
"term": {
"province": {
"value": "湖北"
}
}
},
{
"term": {
"province": {
"value": "北京"
}
}
}
]
}
}
}
#公司不是中国移动
#短信内容包含中国和大地
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"bool": {
"must_not": [
{
"term": {
"corpName": {
"value": "中国移动"
}
}
}
],
"must": [
{
"match": {
"smsContent": "中国"
}
},
{
"match": {
"smsContent": "大地"
}
}
]
}
}
}
# 【注意】must和should混合使用的时候,发现should不起作用了。这个时候可以根据严谨的数据逻辑编写查询语句
# filter查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"bool": {
"filter": [
{
"term":{
"corpName": "中国移动"
}
},
{
"range":{
"fee":{
"gte": 3000
}
}
}
]
}
}
}
filter查询
query:查询到的文档的匹配度会得到分数,并且排序,不会缓存,适合实时查询
filter:查询到的文档不会计算分数,而是会对经常被过滤的数据进行缓存
# filter查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"bool": {
"filter": [
{
"term":{
"corpName": "中国移动"
}
},
{
"range":{
"fee":{
"gte": 3000
}
}
}
]
}
}
}
boosting查询
提升分数查询。默认按照分数,但是有时候想改变一下排序权重
通过将文档原本的_score和negative_boost参数进行相乘来得到新的_score。
positive查询:匹配到了positive查询的文档才会被包含到结果集中
negative查询:满足positive之后,又满足negative,则匹配的文档会被降低其相关度
negative_boost系数小于1.0
# 正常查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"match": {
"smsContent": "北京"
}
}
}
#boosting查询
#短信内容有北京的,公司为中国移动的,则降低其分数
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"boosting": {
"positive": {
"match": {
"smsContent": "北京"
}
},
"negative": {
"match": {
"corpName": "中国移动"
}
},
"negative_boost": 0.2
}
}
}
高亮查询
查询的语句会被高亮显示。
高亮的数据不会影响原来的数据,而是单独将filed对应的数据以高亮返回
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"term": {
"smsContent": "荆楚"
}
}
,
"highlight": {
"fields": {
"smsContent": {
"pre_tags": "",
"post_tags": "",
"fragment_size": 10
}
}
}
}
#结果
{
"_index" : "sms-logs-index",
"_type" : "sms-logs-type",
"_id" : "PbNicHMB9IjDRQti4Hgh",
"_score" : 1.1748445,
"_source" : {
"corpName" : "中国电信",
"smsContent" : "欢迎您来到荆楚大地大地,祝您平安愉快!拨打漫游地区号+12580订票订房;办理移动业务,请拨10086咨询;中国电信荆州公司将竭诚为您服务。",
"fee" : "30",
"province" : "湖北",
"create" : "2020-05-19"
},
"highlight" : {
"smsContent" : [
"欢迎您来到荆楚大地大地"
]
}
}
聚合查询
使用aggs。在查询数据的最后单独展示
1、去重计数cardinality
2、范围统计range。数值range,时间范围date_range,ip范围ip_date。from包含,to不包含。
3、统计查询extended_stats,最大值,最小值,平均值等
经纬度查询
根据地点在地图的坐标,来确定一个范围。看某个点在不在范围中。字段filed的类型为geo_point。
确定范围有,以直线确定一个圆;以2个点确定一个矩形;多个点连接为多边形来确定一个范围。
自此es基础版笔记记录完毕,若想查看es高级功能和原理,请点击es进阶版笔记(待续)
若想安装es和kibana可以移步至docker安装es和kibana——非常简单
【暂完】
正在去BAT的路上修行