前言:本文为原创 若有错误欢迎评论!
- linux安装elasticsearch6.5.4与windows下的kibana 请参考我的博客https://blog.csdn.net/weixin_43934607/article/details/100538881
- 以下的所有操作都是在kibana进行的 如果不在kibana进行操作 用http请求操作
- 路径:http://es的ip:9200/…
- 方法:GET、PUT、POST、DELETE
一.索引
1.创建
PUT /索引库名
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 2
}
}
- settings:索引库的设置
- number_of_shards:分片数量
- number_of_replicas:副本数量
- 同时创建索引与映射
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 2
}
"mappings": {
"集合名": {
"dynamic": false,
"properties": {
"字段1": {
"type": "text",
"analyzer":"ik_max_word"
},
"字段2": {
"type": "keyword",
"index":false
}
}
}
}
}
- dynamic
- dynamic 参数来控制字段的新增
- true:默认值,表示允许选自动新增字段
- false:不允许自动新增字段,但是文档可以正常写入,但无法对字段进行查询等操作
- strict:严格模式,文档不能写入,报错
2.查看
GET /索引库名
3.删除
DELETE /索引库名
二.映射
- 映射是定义文档的过程,文档包含哪些字段,这些字段是否保存,是否索引,是否分词等
1.创建
PUT /索引库名/_mapping/类型名称(表名)
{
"properties": {
"字段名1": {
"type": "类型",
"index": true,
"store": true,
"analyzer": "分词器"
},
"字段名2": {
"type": "类型"
}
}
}
-
type:类型,
- String类型,又分两种:
- text:可分词,不可参与聚合(如标题)
- keyword:不可分词,数据会作为完整字段进行匹配,可以参与聚合(如价格)
- Numerical:数值类型,分两类
- 基本数据类型:long、interger、short、byte、double、float、half_float
- 浮点数的高精度类型:scaled_float , 需要指定一个精度因子,比如10或100。elasticsearch会把真实值乘以这个因子后存储,取出时再还原。
- Date:日期类型
- elasticsearch可以对日期格式化为字符串存储,但是建议我们存储为毫秒值,存储为long,节省空间。
- String类型,又分两种:
-
index:是否索引
- 默认为true
- true:字段会被索引,则可以用来进行搜索。默认值就是true
- false:字段不会被索引,不能用来搜索(如图片的地址)
-
store:是否存储
- 默认为false
- 原因是Elasticsearch在创建文档索引时,会将文档中的原始数据备份,保存到一个叫做 _source 的属性中,如果设置store为true,就会在 _source 以外额外存储一份多余数据
-
analyzer:分词器
- 这里的 ik_max_word 即使用ik分词器(要提前安装插件)
- 分词器即一整个关键词在查询的时候会被拆分成若干个词(汉语是从前到后两个字一个词)
2.查看映射关系
GET /索引库名/_mapping
3.给映射新增对应数据
- 随机生成id
POST /索引库名/类型名
- 自定义id
POST /索引库名/类型名/id
{
"filed1":"value1"
"filed2":"value2"
"filed3":"value3"
}
注意:如果添加数据时的filed在“/索引库/类型名”下不存在 则会给对应的类型中新增该字段
4.修改数据
PUT /索引库名/类型名/id
注意:id对应文档存在,则修改 id对应文档不存在,则新增
5.删除数据
DELETE /索引库名/类型名/id值
三.查询
1.基本查询
GET /索引库名/(类型名)/_search
{
"_source":["filed1","filed2"],
"query":{
"查询类型":{
"查询条件":"查询条件值"
}
}
}
-
查询类型:
match_all、match、term、terms、range、exists等 -
查询返回数据:
- took:查询花费时间,单位是毫秒
- time_out:是否超时 _shards:分片信息
- hits:搜索结果总览对象
- total:搜索到的总条数 max_score:所有结果中文档得分的最高分
- hits:搜索结果的文档对象数组,每个元素是一条搜索到的文档信息
- _index:索引库
- _type:文档类型
- _id:文档id
- _score:文档得分 (每次查询的得分越靠前 排名就越靠前)
- _source:文档的源数据
- filed:字段
-
查询所有(match_all)
{ "query":{ "match_all": {} } }
-
匹配查询(match)
{ "query":{ "match":{ "filed":"value" } } }
- match一次只可以通过一个字段查询
- match作为匹配查询 一般查询的都是一句话如:“aaa bbb ccc”
- 如果查询时路径没有type 则将不分type的匹配该索引库_source中所有包含该字段的数据
- 如果该filed的type为text(即使用了分词器ik_max_word)则会把这个词拆分查询 只要该字段对应的数据包含一个词就会被查找出来 不过包含的词越多 则得分越高 排名越靠前
如果设置了分词 设置匹配度
1)or和and{ "query":{ "match": { "分词字段名": { "query": "查询的值", "operator": "and" } } } }
2)minimum_should_match(最小匹配百分比)
{ "query":{ "match":{ "分词字段名":{ "query":"查询的值", "minimum_should_match": "75%" } } } } #即:在整个词条被拆分之后 最后满足百分之多少个词匹配才会显示
-
词条匹配(term)
{ "query":{ "term":{ "filed":"value" } } } #即:是整个词条完整匹配的精准匹配
多词条精准匹配(terms)
{ "query":{ "terms":{ "filed":[ "value1" "value2" ] } } } #注意filed后面对应多个值时是“[ ]"不是"{ }"
-
exists 返回存在该字段的数据
{ "exists": { "field": "title" } } #查询可以用于查找文档中是否包含指定字段或没有某个字段,类似于SQL语句中的 IS_NULL 条件
-
结果过滤(指定的"_source")
{ "_source": ["filed1","filed2"], "query": { "term": { "filed": "value" } } } #直接指定字段(即用"[ ]"直接写上要显示的字段)
指定includes和excludes
{ "_source": { "includes":["filed1","filed2"] }, "query": { "term": { "filed": "value" } } } #includes:来指定所有字段中要显示的字段
excludes:来指定所有字段中不要显示的字段
{ "_source": { "excludes": ["filed1"] }, "query": { "term": { "filed": "value" } } } #include和exclude不可以同时使用
-
高亮显示
{ "query": { "match": { "name": "张三 李四" } }, "highlight": { "fields": { "name": {} } } } #返回的查询到的数据里的关键字会自动加标签<em>
2.高级查询
-
布尔组合(bool)
- hould:至少有一个查询条件匹配, 相当于 or 。
- must:多个查询条件的完全匹配,相当于 and 。
- must_not:多个查询条件的相反匹配,相当于 not 。
- filter:过滤查询
{ "query":{ "bool":{ "must": [ {"match": { "title": "大米" }} {"term":{"price":999}}, ], "should": [ {"match": { "title": "手机" }} {"term":{"price":999}} ] } } }
filter:过滤(不会影响评分 即不影响原有排名)
{ "query":{ "bool":{ "must":[ { "match": { "title": "小米手机" }} ], "filter":{ "range":{"price":{"gt":2000.00,"lt":3800.00}} } } } }
注意:
- should、must、must_not后面对应的是括号是"[ ]":[ {“查询条件” : {“filed” : “value”} } , { “查询条件” : {“filed” : “value”} } ]
- 其他的像query等多个match或者term查询时 直接就{“查询条件” : {“filed” : “value”} , “查询条件” : {“filed” : “value”} } 就可以 不用每个查询词都带"{ }"
查询和过滤的对比
-
一条过滤语句会询问每个文档的字段值是否包含着特定值。
-
查询语句会询问每个文档的字段值与特定值的匹配程度如何。
- 一条查询语句会计算每个文档与查询语句的相关性,会给出一个相关性评分 _score,并且 按照相关性对匹配到的文档进行排序。 这种评分方式非常适用于一个没有完全配置结果的全文本搜索。
-
一个简单的文档列表,快速匹配运算并存入内存是十分方便的, 每个文档仅需要1个字节。这些缓存的过滤结果集与后续请求的结合使用是非常高效的。
-
查询语句不仅要查找相匹配的文档,还需要计算每个文档的相关性,所以一般来说查询语句要比 过滤语句更耗时,并且查询结果也不可缓存。
-
综上建议:做精确匹配搜索时,最好用过滤语句,因为过滤语句可以缓存数据。
-
范围查询(range)
查询找出那些落在指定区间内的数字或者时间{ "query":{ "range": { "filed": { "gte": 1000.0, "lt": 2800.00 } } } } #注意filed必须是数字类型 #gt:大于 、gte:大于等于 、lt:小于 、lte:小于等于
-
模糊查询(fuzzy)
允许用户搜索词条与实际词条的拼写出现偏差(即错误),但是偏差的编辑距离默认不得超过2{ "query": { "fuzzy": { "title": "appla" } } } #指定fuzziness来设置偏差距离: { "query": { "fuzzy": { "title": { "value":"appla", "fuzziness":1 } } } }
-
排序(sort->order)
sort声明排序、order指定排序方式{ "query": { "match": { "title": "小米手机" } }, "sort": [ { "price": { "order": "desc" }}, { "_score": { "order": "desc" }} ] } #注意:可以指定多个字段排序 按照从上到下的顺序 如果上面的排序结果一致 就再按照下面的排 最终还是相同就按id排
-
权重(boost )
给should里的每个查询加个参数boost 值越大 查询结果得分越靠前{ "query": { "bool": { "must": { "match": { "hobby": { "query": "游泳篮球", "operator": "and" } } }, "should": [ { "match": { "hobby": { "query": "音乐", "boost": 10 } } }, { "match": { "hobby": { "query": "跑步", "boost": 2 } } } ] } }, "highlight": { "fields": { "hobby": {} } } }
-
短语匹配(match_phrase)
分词之后 必须按顺序挨在一起{ "query":{ "match_phrase":{ "hobby":{ "query":"羽毛球篮球" } } }, "highlight": { "fields": { "hobby": {} } } }
可以在分词之后 通过slop设置每个词之间允许跳过几个位置 但必须按照词的顺序
{ "query":{ "match_phrase":{ "hobby":{ "query":"羽毛球篮球" "slop":10 } } }, "highlight": { "fields": { "hobby": {} } } }
3.判断文档是否存在
- 返回状态码,存在200、不存在404
HEAD /索引库名/类型名/id的值
4.批量操作
GET /索引库名/类型名/_mget
{
"ids" : [ "1001", "1003" ]
}
5.分页
- size: 结果数,默认10
- from: 跳过开始的结果数,默认0
GET /_search?size=5
GET /_search?size=5&from=5
四.聚合
1.概念
- 桶(bucket): 桶的作用,是按照某种方式对数据进行分组
常用(使用时关键词为其第一个单词):
- Date Histogram Aggregation:根据日期阶梯分组,例如给定阶梯为周,会自动每周分为一组
- Histogram Aggregation:根据数值阶梯分组,与日期类似
- Terms Aggregation:根据词条内容分组,词条内容完全匹配的为一组
- Range Aggregation:数值和日期的范围分组,指定开始和结束,然后按段分组
-
查询返回值:
"aggregations": { "聚合名": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "字段名1", "doc_count": 4 }, { "key": "字段名2", "doc_count": 2 } ] } }
- 度量(metrics): 分组完成以后对组中的数据进行聚合运算,例如求平均值、最大、最小、求和等
常用:(使用时关键词为其第一个单词)
- Avg Aggregation:求平均值
- Max Aggregation:求最大值
- Min Aggregation:求最小值
- Percentiles Aggregation:求百分比
- Stats Aggregation:同时返回avg、max、min、sum、count等
- Sum Aggregation:求和
- Top hits Aggregation:求前几
- Value Count Aggregation:求总数
-
查询返回值:
"aggregations": { "聚合名(桶)": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "字段名1", "doc_count": 4, "聚合名(度量)": { "value": 32500 } }, { "key": "字段名2", "doc_count": 2, "聚合名(度量)": { "value": 20000 } } } ...
2.查询—聚合为桶
{
"size" : 0,
"aggs" : {
"popular_colors" : {
"terms" : {
"field" : "color"
}
}
}
}
3.查询—桶内度量
{
"size" : 0,
"aggs" : {
"popular_colors" : {
"terms" : {
"field" : "color"
},
"aggs":{
"avg_price": {
"avg": {
"field": "price"
}
}
}
}
}
}
4.查询—桶内嵌套桶
{
"size" : 0,
"aggs" : {
"bocket_name1" : {
"terms" : {
"field" : "price_num"
},
"aggs":{
"avg_price": {
"avg": {
"field": "price_num"
}
},
"bocket_name2":{
"terms":{
"field":"color"
}
}
}
}
}
}
上述的查询条件说明:
size: 查询条数(即hit命中的数据),这里设置为0,因为用不到搜索到的数据,只要聚合结果 提高效率
- aggs:声明这是一个聚合查询,是aggregations的缩写
- bocket_name1:桶聚合的名称 (任意)
- terms:划分桶的方式,这里是根据词条划分
- field:划分桶的字段
- aggs:我们在上一个aggs(popular_colors)中添加新的aggs。可见度量也是一个聚合
- avg_price:聚合的名称(任意)
- avg:度量的类型,这里是求平均值
- field:度量运算的字段
- bocket_name2:桶聚合的名称(任意)
- terms:桶的划分类型依然是词条
- filed:这里根据make字段进行划分
-
即:聚合嵌套聚合(桶或者度量) 下一层聚合时套在上一层的聚合名字里 和上一层的聚合方式同级
-
聚合查询结构:
{
"aggs" : {
"聚合名" : {
"聚合类型(桶或度量)" : {
"field" : "用来聚合的字段名"
}
}
}
}
5.数值阶梯分桶(Histogram->interval)
指明桶的类型为Histogram 再指定一个阶梯值interval
{
"size":0,
"aggs":{
"price":{
"histogram": {
"field": "price",
"interval": 5000
}
}
}
}
如果返回的"key"对应的文档数"doc_count"为0 还可以设置“min_doc_count"来设置最少多少个文档数才会显示
{
"size":0,
"aggs":{
"price":{
"histogram": {
"field": "price",
"interval": 5000,
"min_doc_count": 1
}
}
}
}
6.范围分桶(range)
范围分桶与阶梯分桶类似,也是把数字按照阶段进行分组,只不过range方式需要你自己指定每一组的起始和结束大小