博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Elasticsearch搜索引擎第九篇-搜索API
阅读量:4163 次
发布时间:2019-05-26

本文共 11631 字,大约阅读时间需要 38 分钟。

文章目录

搜索API端点地址

搜索的端点地址可以是多索引多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 搜索

Request body 搜索方式以JSON格式在请求体中定义查询 query。请求方式可以是 GET 、POST ,示例:

GET /twitter/_search{
"query" : {
"term" : {
"user" : "kimchy" } }}

指定返回字段

  • _source字段过滤源文档中包含哪些字段哪些内容
    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" } }}
  • stored_fields指定返回哪些stored的字段
    GET /_search{
    "stored_fields" : "*", "query" : {
    "term" : {
    "user" : "kimchy" } }}GET /_search{
    "stored_fields" : ["user", "postDate"], "query" : {
    "term" : {
    "user" : "kimchy" } }}
  • docvalue_fields指定返回存储了docValue的字段
    GET /_search{
    "query" : {
    "match_all": {
    } }, "docvalue_fields" : ["test1", "test2"]}
  • version指定返回文档的版本字段
    GET /_search{
    "version": true, "query" : {
    "term" : {
    "user" : "kimchy" } }}
  • explain指定返回文档的评分解释(调试比较有用)
GET /_search{
"explain": true, "query" : {
"term" : {
"user" : "kimchy" } }}

script_fields脚本对字段进行运算

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" } }}

sort排序

可以指定按一个或多个字段排序,也可通过_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调试、优化

对于执行缓慢的查询,我们很想知道它为什么慢,时间都耗在哪了,可以在查询上加入上 profile 来获得详细的执行步骤、耗时信息。

GET /twitter/_search{
"profile": true, "query" : {
"match" : {
"message" : "some number" } }}

信息参考官网:

count API

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 }}

validate API

用来检查我们的查询是否正确,以及查看底层生成查询是怎样的,比较常用的一个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" } } }}

explain API

获得某个查询的评分解释,及某个文档是否被这个查询命中

官网:

GET /twitter/_doc/0/_explain{
"query" : {
"match" : {
"message" : "elasticsearch" } }}

分片查询API

让我们可以了解可执行查询的索引分片节点情况:

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/

你可能感兴趣的文章
SuperMap iClient3D for WebGL教程-orientation
查看>>
SuperMap iClient3D for WebGL教程-description描述属性
查看>>
SuperMap iClient3D for WebGL教程-CallbackProperty
查看>>
如何修改leaflet聚合图的层级和样式
查看>>
三维分析之开敞度分析
查看>>
BIM+GIS应用的八大挑战
查看>>
.net实现.aspx页面自动加载.cs程序定义的变量并按照格式输出
查看>>
Spark总结整理(八):Spark Core 性能优化思路、步骤总结
查看>>
实时组件(SparkStreaming VS Flink)容错及语义说明
查看>>
浏览器地址栏输入URL,按下回车后发生了什么
查看>>
linux常用命令
查看>>
网络请求返回HTTP状态码
查看>>
autojs 图片查找比对
查看>>
css 自定义滚动条样式
查看>>
auto js 线程测试
查看>>
ie9走过的坑
查看>>
axios 返回错误消息
查看>>
vue子组件调用父组件的方法
查看>>
vue-element-admin 中使用国际化
查看>>
javascript中常用到的方法和事件
查看>>