本文共 11631 字,大约阅读时间需要 38 分钟。
搜索的端点地址可以是多索引多mapping type的。搜索的参数可作为URI请求参数给出,也可用 request body 给出。
GET /twitter/_search?q=user:kimchyGET /twitter/tweet,user/_search?q=user:kimchyGET /kimchy,elasticsearch/_search?q=tag:wowGET /_all/_search?q=tag:wowGET /_search?q=tag:wow
返回结果说明:
{ "took": 1, #耗时,毫秒 "timed_out": false, #是否超时 "_shards":{ #查询了多少个分片 "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits":{ "total" : 1, #总命中数 "max_score": 1.3862944, #最高得分 "hits" : [ #本业结果文档数组 { "_index" : "twitter", #索引名称 "_type" : "_doc", #mapping type "_id" : "0", #文档ID "_score": 1.3862944, #相关性得分 "_source" : { "user" : "kimchy", "message": "trying out Elasticsearch", "date" : "2009-11-15T14:12:12", "likes" : 0 } } ] }}
URI 搜索方式通过URI参数来指定查询相关参数。让我们可以快速做一个查询。可用的参数请参考官网:
如果我们只想知道有多少文档匹配某个查询,可以这样用参数:
GET /bank/_search?q=city:b*&size=0
如果我们只想知道有没有文档匹配某个查询,可以这样用参数:
GET /bank/_search?q=city:b*&size=0&terminate_after=1
Request body 搜索方式以JSON格式在请求体中定义查询 query。请求方式可以是 GET 、POST ,示例:
GET /twitter/_search{ "query" : { "term" : { "user" : "kimchy" } }}
GET /_search{ "_source": false, "query" : { "term" : { "user" : "kimchy" } }}GET /_search{ "_source": "obj.*", "query" : { "term" : { "user" : "kimchy" } }}GET /_search{ "_source": [ "obj1.*", "obj2.*" ], "query" : { "term" : { "user" : "kimchy" } }}GET /_search{ "_source": { "includes": [ "obj1.*", "obj2.*" ], "excludes": [ "*.description" ] }, "query" : { "term" : { "user" : "kimchy" } }}
GET /_search{ "stored_fields" : "*", "query" : { "term" : { "user" : "kimchy" } }}GET /_search{ "stored_fields" : ["user", "postDate"], "query" : { "term" : { "user" : "kimchy" } }}
GET /_search{ "query" : { "match_all": { } }, "docvalue_fields" : ["test1", "test2"]}
GET /_search{ "version": true, "query" : { "term" : { "user" : "kimchy" } }}
GET /_search{ "explain": true, "query" : { "term" : { "user" : "kimchy" } }}
GET /bank/_search{ "query": { "match_all": { } }, "script_fields": { "test1": { "script": { "lang": "painless", "source": "doc['balance'].value * 2" } }, "test2": { "script": { "lang": "painless", "source": "doc['age'].value * params.factor", "params": { "factor": 2 } } } }}
min_score限制最低评分得分
GET /_search{ "min_score": 0.5, "query" : { "term" : { "user" : "kimchy" } }}
post_filter后置过滤:在查询命中文档、完成聚合后,再对命中的文档进行过滤
如:要在一次查询中查询品牌为gucci且颜色为红色的shirts,同时还要得到gucci品牌各颜色的shirts的分面统计。
PUT /shirts{ "mappings": { "_doc": { "properties": { "brand": { "type": "keyword"}, "color": { "type": "keyword"}, "model": { "type": "keyword"} } } }}PUT /shirts/_doc/1?refresh{ "brand": "gucci", "color": "red", "model": "slim"}PUT /shirts/_doc/2?refresh{ "brand": "gucci", "color": "green", "model": "seec"}GET /shirts/_search{ "query": { "bool": { "filter": { "term": { "brand": "gucci" } } } }, "aggs": { "colors": { "terms": { "field": "color" } } }, "post_filter": { "term": { "color": "red" } }}
可以指定按一个或多个字段排序,也可通过_score指定按评分值排序,_doc 按索引顺序排序。默认是按相关性评分从高到低排序。
GET /bank/_search{ "query": { "match_all": { } }, "sort": [ { "age": { "order": "desc" } }, { "balance": { "order": "asc" } }, "_score" ]}
返回结果:
"hits": { "total": 1000, "max_score": null, "hits": [ { "_index": "bank", "_type": "_doc", "_id": "549", "_score": 1, "_source": { "account_number": 549, "balance": 1932, "age": 40, "state": "OR" }, "sort": [ 40, 1932, 1 ] } }
- order值为asc、desc,默认asc
- _score默认是desc
- 结果中每个文档都会有排序字段值给出
对于值是数组或多值的字段,也可进行排序,通过mode参数指定按多值的哪种类型排序,总共有如下几种类型:
- min:最小值
- max:最大值
- sum:和
- avg:平均值
- median:中值
PUT /my_index/_doc/1?refresh{ "product": "chocolate", "price": [20, 4]}POST /_search{ "query" : { "term" : { "product" : "chocolate" } }, "sort" : [ { "price" : { "order" : "asc", "mode" : "avg"}} ]}
索引中,可能有的文档有该字段,有的文档没有该字段,那么在查询的时候可以指定若没有该字段的文档应该如何排序:
- _last:表示没有该字段的文档排在后面
- _first:表示没有该字段的文档排在前面
GET /_search{ "sort" : [ { "price" : { "missing" : "_last"} } ], "query" : { "term" : { "product" : "chocolate" } }}
GET /_search{ "sort" : [ { "_geo_distance" : { #距离排序关键字 "pin.location" : [-70, 40], #geo_point类型的字段 "order" : "asc", "unit" : "km", #距离单位,km、m,默认m "mode" : "min", "distance_type" : "arc" #距离计算方式,arc球面、plan平面 } } ], "query" : { "term" : { "user" : "kimchy" } }}
详细的参考官方文档:
GET /_search{ "query" : { "term" : { "user" : "kimchy" } }, "sort" : { "_script" : { "type" : "number", "script" : { "lang": "painless", "source": "doc['field_name'].value * params.factor", "params" : { "factor" : 1.1 } }, "order" : "asc" } }}
用collapse指定根据某个字段对命中结果进行折叠
GET /bank/_search{ "query": { "match_all": { } }, "collapse" : { "field" : "age" }, "sort": ["balance"] }
解释:先根据条件查询出结果,然后按照age字段分组,每个分组按照balance升序排序,接着从每个分组中取出第一条数据
仅仅从上述语句,我们很难判断查询结果正确与否,因此es还提供了inner_hits方式,可以在调试的时候解释折叠的结果,使用方式如下:
GET /bank/_search{ "query": { "match_all": { } }, "collapse" : { "field" : "age" , "inner_hits": { #指定inner_hits来解释折叠 "name": "details", #自定义命名 "size": 5, #指定每组取几个文档 "sort": [{ "balance": "asc" }] #组内排序 }, "max_concurrent_group_searches": 4 #指定组查询的并发数 }, "sort": ["balance"] }
除此之外,inner_hits还可以返回多个角度的组内topN
GET /twitter/_search{ "query": { "match": { "message": "elasticsearch" } }, "collapse" : { "field" : "user", "inner_hits": [ { "name": "most_liked", "size": 3, "sort": ["likes"] }, { "name": "most_recent", "size": 3, "sort": [{ "date": "asc" }] } ] }, "sort": ["likes"]}
普通分页:
GET /_search{ "from" : 0, "size" : 10, "query" : { "term" : { "user" : "kimchy" } }}
注意:搜索请求耗用的堆内存和时间与 from + size 大小成正比。分页越深耗用越大,为了不因分页导致OOM或严重影响性能,ES中规定from + size 不能大于索引setting参数 index.max_result_window 的值,默认值为 10000。
search_after在指定文档后面取文档,可用于深度分页,即在获取下一页的时候需要传入上次获取的最后一个文档。注意:使用search_after,要求查询必须指定排序,并且这个排序组合值在每个文档唯一(最好排序中包含_id字段,这样可以保证唯一)。 search_after的值用的就是这个排序值。用search_after时 from 只能为0、-1。
首次查询第一页:GET twitter/_search{ "size": 10, "query": { "match" : { "title" : "elasticsearch" } }, "sort": [ { "date": "asc"}, { "_id": "desc"} ]}
后续的查询:
GET twitter/_search{ "size": 10, "query": { "match" : { "title" : "elasticsearch" } }, "search_after": [1463538857, "654323"], #传入上次最后一个文档排序的内容 "sort": [ { "date": "asc"}, { "_id": "desc"} ]}
GET twitter/_search{ "size": 10, "query": { "match" : { "title" : "elasticsearch" } }, "search_after": [1463538857, "654323"], "sort": [ { "date": "asc"}, { "_id": "desc"} ]}#这种写法只会高亮第一个字段titleGET /hl_test/_search{ "query": { "match": { "title": "lucene" } }, "highlight": { "fields": { "title": { }, "content": { } } }}#require_field_match多字段高亮GET /hl_test/_search{ "query": { "match": { "title": "lucene" } }, "highlight": { "require_field_match": false, "fields": { "title": { }, "content": { } } }}
高亮结果在返回的每个文档中以hightlight节点给出:
"highlight": { "title": [ "lucene solr and elaticsearch" ]}
如果高亮标签不想使用默认的em,可以自定义高亮标签:
GET /hl_test/_search{ "query": { "match": { "title": "lucene" } }, "highlight": { "require_field_match": false, "fields": { "title": { "pre_tags":[""], "post_tags": [""] }, "content": { } } }}
高亮的详细设置请参考官网:
对于执行缓慢的查询,我们很想知道它为什么慢,时间都耗在哪了,可以在查询上加入上 profile 来获得详细的执行步骤、耗时信息。
GET /twitter/_search{ "profile": true, "query" : { "match" : { "message" : "some number" } }}
信息参考官网:
count查询:
PUT /twitter/_doc/1?refresh{ "user": "kimchy"}GET /twitter/_doc/_count?q=user:kimchyGET /twitter/_doc/_count{ "query" : { "term" : { "user" : "kimchy" } }}
返回结果:
{ "count" : 1, "_shards" : { "total" : 5, "successful" : 5, "skipped" : 0, "failed" : 0 }}
用来检查我们的查询是否正确,以及查看底层生成查询是怎样的,比较常用的一个API
官网: 校验查询:GET twitter/_doc/_validate/query{ "query": { "query_string": { "query": "post_date:foo", "lenient": false } }}
获得查询解释:
GET twitter/_doc/_validate/query?explain=true{ "query": { "query_string": { "query": "post_date:foo", "lenient": false } }}
用rewrite获得比explain更详细的解释:
GET twitter/_doc/_validate/query?rewrite=true{ "query": { "more_like_this": { "like": { "_id": "2" }, "boost_terms": 1 } }}
获得所有分片上的解释:
GET twitter/_doc/_validate/query?rewrite=true&all_shards=true{ "query": { "match": { "user": { "query": "kimchy", "fuzziness": "auto" } } }}
获得某个查询的评分解释,及某个文档是否被这个查询命中
官网:GET /twitter/_doc/0/_explain{ "query" : { "match" : { "message" : "elasticsearch" } }}
让我们可以了解可执行查询的索引分片节点情况:
GET /twitter/_search_shards
想知道指定routing值的查询将在哪些分片节点上执行:
GET /twitter/_search_shards?routing=foo,baz
很多时候,我们可能会碰到相同的查询情况,这时候就可以定义一个查询模板,然后使用模板进行查询。
注册一个模板:
POST _scripts/{ "script": { "lang": "mustache", "source": { "query": { "match": { "title": "{ {query_string}}" } } } }}
使用模板查询:
GET _search/template{ "id": "", #指定之前注册的模板名称 "params": { "query_string": "search for these words" #传入查询字符串 }}
详细请参考官网:
转载地址:http://ggsxi.baihongyu.com/