ES高级操作
结果过滤
默认情况下,elasticsearch在搜索的结果中,会把文档中保存在_source
的所有字段都返回。
如果我们只想获取其中的部分字段,我们可以添加_source
的过滤
直接指定字段
示例:
POST /heima/_search { "_source": ["title","price"], "query": { "term": { "price": 2699 } } }
返回的结果:
{ "took": 4, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 1, "max_score": 1, "hits": [ { "_index": "heima", "_type": "goods", "_id": "3q3hTW0BTp_XthqB2lMR", "_score": 1, "_source": { "price": 2699, "title": "小米手机" } } ] } }
指定includes和excludes
我们也可以通过:
- includes:来指定想要显示的字段
- excludes:来指定不想要显示的字段
二者都是可选的。
示例:
POST /heima/_search { "_source": { "includes":["title","price"] }, "query": { "term": { "price": 2699 } } }
与下面的结果将是一样的:
POST /heima/_search { "_source": { "excludes": ["images"] }, "query": { "term": { "price": 2699 } } }
结果:
{ "took": 2, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 1, "max_score": 1, "hits": [ { "_index": "heima", "_type": "goods", "_id": "3q3hTW0BTp_XthqB2lMR", "_score": 1, "_source": { "price": 2699, "title": "小米手机" } } ] } }
高级查询
布尔组合(bool)
bool
把各种其它查询通过must
(与)、must_not
(非)、should
(或)的方式进行组合
GET /heima/_search { "query":{ "bool":{ "must": { "match": { "title": "小米" }}, "must_not": { "match": { "title": "电视" }}, "should": { "match": { "title": "手机" }} } } }
结果:
{ "took": 134, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 1, "max_score": 1.0884295, "hits": [ { "_index": "heima", "_type": "goods", "_id": "3q3hTW0BTp_XthqB2lMR", "_score": 1.0884295, "_source": { "title": "小米手机", "images": "http://image.leyou.com/12479122.jpg", "price": 2699 } } ] } }
范围查询(range)
range
查询找出那些落在指定区间内的数字或者时间
range
查询允许以下字符:
操作符 | 说明 |
---|---|
gt | 大于 |
gte | 大于等于 |
lt | 小于 |
lte | 小于等于 |
示例:
POST /heima/_search { "query":{ "range": { "price": { "gte": 3000, "lt": 5000 } } } }
结果:
{ "took": 7, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 2, "max_score": 1, "hits": [ { "_index": "heima", "_type": "goods", "_id": "3a3hTW0BTp_XthqB2lMR", "_score": 1, "_source": { "title": "大米手机", "images": "http://image.leyou.com/12479122.jpg", "price": 3288 } }, { "_index": "heima", "_type": "goods", "_id": "363hTW0BTp_XthqB2lMR", "_score": 1, "_source": { "title": "小米电视4A", "images": "http://image.leyou.com/12479122.jpg", "price": 4288 } } ] } }
模糊查询(fuzzy)
我们新增一个商品:
POST /heima/goods/4 { "title":"apple手机", "images":"http://image.leyou.com/12479122.jpg", "price":5899.00 }
fuzzy自动将拼写错误的搜索文本,进行纠正,纠正以后去尝试匹配索引中的数据
它允许用户搜索词条与实际词条出现偏差,但是偏差的编辑距离不得超过2:
POST /heima/_search { "query": { "fuzzy": { "title": "appla" } } }
上面的查询,也能查询到apple手机
fuzziness,你的搜索文本最多可以纠正几个字母去跟你的数据进行匹配,默认如果不设置,就是2我们可以通过
POST /heima/_search { "query": { "fuzzy": { "title": { "value": "applaa", "fuzziness": 2 } } } }
排序
单字段排序
sort
可以让我们按照不同的字段进行排序,并且通过order
指定排序的方式
POST /heima/_search { "query": { "match_all": {} }, "sort": [ {"price": {"order": "desc"}} ] }
多字段排序
假定我们想要结合使用 price和 _score(得分) 进行查询,并且匹配的结果首先按照价格排序,然后按照相关性得分排序:
POST /heima/_search { "query":{ "match_all":{} }, "sort": [ { "price": { "order": "desc" }}, { "_score": { "order": "desc" }} ] }
高亮
elasticsearch中实现高亮的语法比较简单:
POST /heima/_search { "query": { "match": { "title": "电视" } }, "highlight": { "pre_tags": "<font color='pink'>", "post_tags": "</font>", "fields": { "title": {} } } }
在使用match查询的同时,加上一个highlight属性:
-
pre_tags:前置标签
-
post_tags:后置标签
-
fields:需要高亮的字段
- title:这里声明title字段需要高亮,后面可以为这个字段设置特有配置,也可以空
结果:
{ "took": 12, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 1, "max_score": 0.90204775, "hits": [ { "_index": "heima", "_type": "goods", "_id": "363hTW0BTp_XthqB2lMR", "_score": 0.90204775, "_source": { "title": "小米电视4A", "images": "http://image.leyou.com/12479122.jpg", "price": 4288 }, "highlight": { "title": [ "小米<font color='pink'>电视</font>4A" ] } } ] } }
分页
elasticsearch中实现分页的语法非常简单:
POST /heima/_search { "query": { "match_all": {} }, "size": 2, "from": 0 }
size:每页显示多少条
from:当前页起始索引, int start = (pageNum - 1) * size;
小案例
制作测试数据
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
PUT /goods/fruit/1 { "name": "xiangjiao", "describe": "haochi tian", "price": 40, "producer": "feilvbin", "tags": [ "xiangjiao", "haochi" ] } PUT /goods/fruit/2 { "name":"pingguo", "describe":"cui", "price":60, "producer":"zhongguo", "tags":["haokan","xiang"] } PUT /goods/fruit/3 { "name":"lizi", "describe":"zide", "price":10, "producer":"zhongguo", "tags":["suan","tian"] } PUT /goods/fruit/4 { "name":"boluo", "describe":"getouda", "price":74, "producer":"malaxiya", "tags":["huang","youci"] } PUT /goods/fruit/5 { "name":"mihoutao", "describe":"suan", "price":45, "producer":"xinxilan", "tags":["lv","huang"] } PUT /goods/fruit/6 { "name":"xigua", "describe":"haochi", "price":109, "producer":"zhongguo", "tags":["da","haochi"] }
查询所有数据
GET goods/fruit/_search { "query": { "match_all": {} } }
排序查询
GET goods/fruit/_search { "query": { "match": { "name": "pingguo" } }, "sort": { "price": { "order": "asc" } } }
每页显示2条数据,无序的话,按照默认排序
GET goods/fruit/_search { "query": { "match": { "name": "pingguo" } }, "sort": { "price": { "order": "asc" } }, "from": 0, "size": 2 }
使用 “_source” 查询指定字段的数据
GET goods/fruit/_search { "query": { "match_all": {} }, "_source": ["name", "producer"] }
bool查询
bool的方式,根据指定字段查询数据。
GET goods/fruit/_search { "query": { "bool": { "must": [ { "match": { "name": "pingguo" } } ] } } }
bool多条件查询,相当于sql的and语句。
GET goods/fruit/_search { "query": { "bool": { "must": [ { "match": { "name": "pingguo" } }, { "match": { "producer": "zhongguo" } } ] } } }
bool多条件或查询,相当于sql的or语句
GET goods/fruit/_search { "query": { "bool": { "should": [ { "match": { "name": "pingguo" } }, { "match": { "producer": "zhongguo" } } ] } } }
bool多条件非查询,相当于sql的not语句
GET goods/fruit/_search { "query": { "bool": { "must_not": [ { "match": { "name": "pingguo" } }, { "match": { "producer": "zhongguo" } } ] } } }
按条件查询
查询name是pingguo的,然后价钱大于100的数据(里可以使用should但是不建议使用should,会出现异常错误)
GET goods/fruit/_search { "query": { "bool": { "must": [ { "match": { "name": "pingguo" } } ], "filter": [ { "range": { "price": { "gt": 100 } } } ] } } }
短语检索
通过检索数组类型的数据,可直接通过全文检索,匹配多个值,通过空格间隔。
GET goods/fruit/_search { "query": { "match": { "tags": "da lv" } } }
短语匹配,就像 match
查询对于标准全文检索是一种最常用的查询一样,当你想找到彼此邻近搜索词的查询方法时,就会想到 match_phrase
查询。
GET goods/fruit/_search { "query": { "match_phrase": { "name": "pingguo" } } }
高亮显示(highlight)
GET goods/fruit/_search { "query": { "match": { "name": "pingguo" } }, "highlight": { "pre_tags": "<b style='color: red'>", "post_tags": "</b>", "fields": { "name": {} } } }
聚合函数(先查询,在聚合,分段式)
查询出来的数据,选择指定字段计算平均值,例如计算价钱平均值。 sum 总数,avg 平均值
前20的平局值
GET goods/fruit/_search { "from": 0, "size": 20, "aggs": { "avg_price": { "avg": { "field": "price" } } } }
默认会同时展示计算结果与查询出来的数据,如果不想要查询出来的数据,将 size 设置为0
bool查询后,进行聚合函数处理(查询苹果价格大于100的价格总数)
GET goods/fruit/_search { "query": { "bool": { "must": [ { "match": { "name": "pingguo" } } ], "filter": [ { "range": { "price": { "gte": 100 } } } ] } }, "aggs": { "c": { "sum": { "field": "price" } } } }
分段查询后,进行聚合函数处理
GET goods/_search { "size": 0, "aggs": { "f": { "range": { "field": "price", "ranges": [ { "from": 0, "to": 50 }, { "from": 50, "to": 100 }, { "from": 100, "to": 150 } ] }, "aggs": { "sum_price": { "sum": { "field": "price" } } } } } }
输出结果如下
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
{ "took" : 11, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : 7, "max_score" : 0.0, "hits" : [ ] }, "aggregations" : { "f" : { "buckets" : [ { "key" : "0.0-50.0", "from" : 0.0, "to" : 50.0, "doc_count" : 3, "sum_price" : { "value" : 95.0 } }, { "key" : "50.0-100.0", "from" : 50.0, "to" : 100.0, "doc_count" : 2, "sum_price" : { "value" : 134.0 } }, { "key" : "100.0-150.0", "from" : 100.0, "to" : 150.0, "doc_count" : 2, "sum_price" : { "value" : 218.0 } } ] } } }
mapping
查询mapping
GET goods/_mapping
新建mappings
dynamic的三个参数
-
1. false 不会为新增的字段数据不会创建索引(也就是用不存在mapping中的字段检索是检索不出来的)
-
2. true 会为所有数据属性创建索引,包括新建的字段属性
-
3. strict 必须添加指定的属性,添加动态属性的时候,会报错。
PUT my_index1 { "mappings": { "a": { "dynamic": false, "properties": { "name": { "type": "text" }, "age": { "type": "long" } } } } }
copy_to属性
copy_to属性,把当前属性的值复制给指定的字段
PUT my_index2 { "mappings": { "doc": { "dynamic": false, "properties": { "first_name": { "type": "text", "copy_to":"full_name" }, "last_name": { "type": "lotextng" }, "full_name": { "type": "lotextng" } } } } }
index属性
index属性,默认为true,如果设置为false,则当前属性不能被创建索引。及不能通过当前属性进行数据的筛选、搜索、查询等操作
PUT my_index2 { "mappings": { "doc": { "dynamic": false, "properties": { "first_name": { "type": "text", "index": true }, "last_name": { "type": "text", "index": false } } } } }
对象型属性
创建对象型数据
PUT my_index3/doc/2 { "name": "tom", "age": 11, "add": { "address": "bj", "tel": "13333333333" } }
根据嵌套的属性数据进行过滤查询
GET my_index3/doc/_search { "query": { "match": { "add.address": "bj" } } }
ik分词器
ik分词器是按照词来分,单个字查不出来,es默认是按照字来分单个汉子也能查出来
创建mapping
PUT my_index7 { "mappings": { "doc": { "dynamic": false, "properties": { "content": { "type": "text", "analyzer":"ik_max_word" } } } } }
添加数据
PUT my_index7/doc/1 { "content":"今天是个好日子" } PUT my_index7/doc/2 { "content":"心想的事儿都能成" }
模糊查询
GET my_index7/_search { "query": { "match": { "content": "日子" } } }
单个查不出来
GET my_index7/_search { "query": { "match": { "content": "日" } } }
es默认的分词器
PUT my_index8 { "mappings": { "doc": { "dynamic": false, "properties": { "content": { "type": "text" } } } } } PUT my_index8/doc/1 { "content":"心想的事儿都能成" } GET my_index8/_search { "query": { "match": { "content": "事" } } }
ik 最粗粒度分词,内容文章类的使用,标题的使用细的分词粒度
_all 不用重复定义,全局通用
PUT my_index9/ { "mappings": { "doc": { "_all": { "analyzer": "ik_smart" }, "properties": { "content": { "type": "text" } } } } }
短语查询和前缀查询
中文来说尽量使用短语查询
GET my_index8/_search { "query": { "match_phrase": { "content": "心想" } } }
类似上面
GET my_index8/_search { "query": { "match_phrase_prefix": { "content": "心想" } } }