本篇主要介绍常见的6种搜索方式、聚合分析语法,基本是上机实战,可以和关系型数据库作对比,如果之前了解关系型数据库,那本篇只需要了解搜索和聚合的语法规则就可以了。
搜索响应报文以上篇建立的music索引为例,我们先看看搜索结果的属性都有哪些
{ "took": 1, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 1, "max_score": 1, "hits": [ { "_index": "music", "_type": "children", "_id": "1", "_score": 1, "_source": { "name": "gymbo", "content": "I hava a friend who loves smile, gymbo is his name", "length": "75" } } ] } }主要的参数说明如下:
took:耗费时间,单位是毫秒。
timed_out:是否超时,true有超时,false没超时。
_shards:数据拆成了5个分片,所以对于搜索请求,会到所有的primary shard查询,或是它的某个replica shard。
hits.total:符合查询条件的数量,1个document。
hits.max_score:score是符合条件的document评分的最大值。
hits.hits.score: 这个层级的score表示当前document对search条件的相关度的匹配分数,越相关,就越匹配,分数也高。
hits.hits:包含了匹配搜索条件的document的详细数据。
搜索方式 query string search搜索所有数据
GET /music/children/_search
带条件搜索
GET /music/children/_search?q=name:gymbo&sort=length:asc
此搜索语法的特点是所有的条件、排序全部用http请求的query string来附带的。这种语法一般是演示或curl命令行简单查询时使用,不适用构建复杂的查询条件,生产已经很少用了。
Query DSLDSL:Domain Specified Language特定领域语言
http request body:请求体格式,body用json构建语法,可以构建各种复杂的语法。
查询所有数据
GET /music/children/_search { "query":{ "match_all": {} } }带条件+排序:
GET /music/children/_search { "query":{ "match": { "name": "gymbo" } }, "sort":[{"length":"desc"}] }分页查询,size从0开始,下面的命令取第10条到第19条数据
GET /music/children/_search { "query": { "match_all":{} }, "from": 10, "size": 10 }指定要查询出来的属性
GET /music/children/_search { "query": { "match_all" : {} }, "_source": ["name","content"] } query filter带多个条件过滤:歌曲名称是gymbo,并且时长在65到80秒之间的
GET /music/children/_search { "query":{ "bool":{ "must": [ {"match": { "name": "gymbo" }} ], "filter": {"range": { "length": { "gte": 65, "lte": 80 } }} } } } 全文检索 GET /music/children/_search { "query":{ "match": { "content":"friend smile" } } }搜索的结果是按相关度分数来排序的,搜索条件中的content field,在新增document时已经建立倒排索引,然后按匹配度最高的来排序,全文索引的原理。
短语检索 GET /music/children/_search { "query":{ "match_phrase": { "content":"friend smile" } } }全文检索match会拆词,大小写不敏感,然后去倒排索引里去匹配,phrase search不分词,大小写敏感,要求搜索串完全一样才匹配。
高亮检索 GET /music/children/_search { "query":{ "match_phrase":{ "content":"friend smile" } }, "highlight": { "fields": { "content":{} } } }匹配的关键词会高亮显示,高亮的内容用标签达到标记效果。
聚合分析聚合分析类似于关系型数据的分组统计,并且用的语法名称很多都与mysql类似,在这里,能看到很多熟悉的方法。
单field分组统计需求:统计每种语言下的歌曲数量。
size为0表示不显示符合条件的document记录,只显示统计信息,不写的话默认值是10
GET /music/children/_search { "size": 0, "aggs": { "group_by_lang": { "terms": { "field": "language" } } } }响应结果:
{ "took": 3, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 1, "max_score": 0, "hits": [] }, "aggregations": { "group_by_lang": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "english", "doc_count": 1 } ] } } }如果聚合查询时出现如下错误提示:
"root_cause": [ { "type": "illegal_argument_exception", "reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [language] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead." } ]需要将用于分组的字段的fielddata属性设置为true
PUT /music/_mapping/children { "properties": { "language": { "type": "text", "fielddata": true } } } 带查询条件的分组统计需求:对歌词中出现"friend"的歌曲,计算每个语种下的歌曲数量
GET /music/children/_search { "size": 0, "query": { "match": { "content": "friend" } }, "aggs": { "all_languages": { "terms": { "field": "language" } } } } 求平均值