超时(timeout)
- 用法: GET /_search?timeout=1s/ms/m (秒/毫秒/分)
- 设置:默认es没有timeout,如果设置timeout,则执行timeout机制。
- timeout机制:每个share只能在timeout指定的时间范围内,将搜索到的部分数据(或全部搜索到的数据),直接返回给客户端,而不是待数据全部查询出来之后,再返回给客户端。【指定时间内,取到多少,返回多少】
ES常用查询
-
query_string
查询指定索引所有: GET /索引名/_search
-
查询指定所以特定条件数据:
GET /索引名/_search?q=字段名称:字段值 如 GET /product/_search?q=name:nfc
分页:GET /索引名/_search?from=页码&size=条数&q=字段名称:字段值
-
query_dsl (英语:domain-specific language、DSL)
-
match_all : 匹配指定索引所有
GET /product/_search { "query": { "match_all": {} } }
-
match 匹配所有中name字段含有nfc的数据
GET /product/_search { "query": { "match": { "name": "nfc" } } }
-
sort 按照价格倒叙排序。一但排序,则_score值为null
GET /product/_search { "query": { "match_all": {} } , "sort": [ { "price": { "order": "desc" } } ] }
-
multi_match 根据多个字段查询关键词。name和desc中任何一个字段包含“nfc”的doc
GET /product/_search { "query": { "multi_match": { "query": "nfc", "fields": ["name","desc"] } } }
-
_source : 指定查询字段。查询name和price字段
GET /product/_search { "query": { "multi_match": { "query": "nfc", "fields": ["name","desc"] } } , "_source": ["name","price"] }
-
分页 查询第二页,每页两条数据
GET /product/_search { "query": { "match_all": {} } , "sort": [ { "price": { "order": "desc" } } ] , "from": 1 , "size": 2 }
-
-
全文检索(full-text-query)
-
query-term 不会被分词, 体会term terms 和 match 区别
GET /product/_search { "query": { "term": { "name": { "value": "nfc" } } } } /** * 体会与match的区别 **/ GET /product/_search { "query": { "term": { "name": { "value": "nfc phone" // 作为一个分词(整体)与name字段匹配 } } } } GET /product/_search { "query": { "match": { "name": "nfc phone" // 被分词器分为 nfc 和 phone 两个分词与name字段匹配 } } } // name中必须(must)含有xiaomi 和 nfc 两个条件 GET /product/_search { "query": { "bool": { "must": [ {"term": { "name": { "value": "xiaomi" } }} ,{"term": { "name": { "value": "nfc" } }} ] } } } // 两个单独的分词“nfc”和“xiaomi” (一定是两个分词) 两个分词与name进行匹配 GET /product/_search { "query": { "terms": { "name": [ "nfc", "xiaomi" ] } } } // 字符串“nfc iphone” 被分词有在与name配置,是否被分词两个字要看分词器的分词结果。逻辑上“nfc iphone”有可能作为一个整体。 GET /product/_search { "query": { "match": { "name": "nfc iphone" } } }
-
验证分词
GET /_analyze { "analyzer": "standard" , "text": ["xiaomi nfc zhineng phone"] } 分词结果 { "tokens" : [ { "token" : "xiaomi", "start_offset" : 0, "end_offset" : 6, "type" : "<ALPHANUM>", "position" : 0 }, { "token" : "nfc", "start_offset" : 7, "end_offset" : 10, "type" : "<ALPHANUM>", "position" : 1 }, { "token" : "zhineng", "start_offset" : 11, "end_offset" : 18, "type" : "<ALPHANUM>", "position" : 2 }, { "token" : "phone", "start_offset" : 19, "end_offset" : 24, "type" : "<ALPHANUM>", "position" : 3 } ] }
-
-
短语搜索(phrase search),和全文搜索相反,
GET /product/_search { "query": { "match_phrase": { "name": "nfc iphone" } } } 1>: name字段会被分词器分词 2>: 被搜索文本中出现name所有分词后的字段,并且文本内容必须和name分词之后的词出现的顺序一致。
查询和过滤
-
bool 查询:可以组合多个查询条件,bool查询采用more_matches_is_better的机制,因此满足must和should子句的文档将会合并起来计算分值。
must :必须满足。 子语句(查询)必须出现在匹配的文档中,相当于sql中and
-
must_not:必须不满足,不计算相关分数。相当于sql中 not。
子句(查询)不得出现的匹配文档中,子句在过滤器上下文中执行,这意味着计分被忽略,并且子句被视为用于缓存。
- should :可能满足。相当于sql中的or。子句(查询)应出现在匹配的文档中。
-
filter:过滤器,不计算相关度分数,应用cache;
子句(查询)必须出现在匹配的文档中,但是不行must查询的分数被忽略。filter子句在filter上下文中被执行,意味着计分被忽略,并且子句被考虑用于缓存。
-
精彩案例
-
筛选name包含“xiaomi phone” 并且价格大于1999的数据(不排序),搜索name包含“xiaomi” and desc包含“shouji”
GET /product/_search { "query": { "bool": { "must": [ {"match": { "name": "xiaomi" }} ,{"match": { "desc": "shouji" }} ] , "filter": [ { "match_phrase": { "name": "xiaomi phone" } } ,{"range": { "price": { "gt": 1999 } }} ] } } }
-
-
bool 多条件,name包含“xiaomi”, 不包含“erji”。desc里包不包含“nfc”都可以。价格大于等于2999
GET /product/_search { "query": { "bool": { "must": [ {"match": { "name": "xiaomi" }} ] , "must_not": [ {"match": { "name": "erji" }} ] ,"should": [ {"match": { "desc": "nfc" }} ] ,"filter": [ {"range": { "price": { "gt": 2999 } }} ] } } }
-
嵌套查询
minimun_should_match:参数指定should 返回的文档必须匹配的子句的数量或者百分比。should查询条件粗只能在时,如果有别的查询条件,如must、must_not、filter,则默认为0,否则为1。如果为0,则should条件可以一个都不满足,如果为1,则should的两个条件满足任何一个就可以,如果为2,则两个条件必须都满足。
GET /product/_search { "query": { "bool": { "must": [ {"match": { "name": "nfc" }} ] , "should": [ {"range": { "FIELD": { "gte": 1999 } }} ,{ "range": { "FIELD": { "gte": 3999 } } } ] ,"minimum_should_match": 1 } } } 1>:must 不存在,则 minimum_should_match 默认为1, should 下的range必须生效一个。 2>:must 存在,则 minimum_should_match 默认为0, should下的range可都不生效,可生效一个或者两个。 3>:minimum_should_match 设置,以设置的值为准。
-
组合查询(compound queries)
constant_score 搜索结果忽略词频(TF)对搜索结果排序的影响。将查询语句或者过滤语句包装起来。
检索词词频:检索词在该字段出现的频率。出现频率越高,相关性越高。字段中出现过5次要不只出现1次的相关性高。
-
想要一台NFC功能的或者小米手机, 但是不要带耳机的。
GET /product/_search { "query": { "bool": { "should": [ {"term": { "name": { "value": "nfc" } }} ,{"term": { "name": { "value": "xiaomi" } }} ] , "must_not": [ {"term": { "name": { "value": "erji" } }} ] , "minimum_should_match": 1 } } }
-
搜索一台“xiaoami nfc phone”或者(一台手机或者几个小于等于2999)
GET /product/_search { "query": { "constant_score": { "filter": { "bool": { "should": [ { "match_phrase": { "name": "xiaomi nfc phone" } }, { "bool": { "filter": [ { "match_phrase": { "name": "phone" } }, { "range": { "price": { "gte": 2999 } } } ] } } ] , "minimum_should_match": 1 } }, "boost": 1.2 } } }
-
高亮(hightlight search)
GET /product/_search { "query": { "match_phrase": { "name": "nfc phone" } } , "highlight": { "fields": { "name": {} } } }
-
deep paging
- 概念理解:简单来说所,就是搜索的特别深。假如说现在es中有60000条记录,分别存在3个primary shard中,则每个primary shard要存20000条记录。
- 出现的问题:如果要取第1000页(每页10条)数据,则需要在每个primary shard中取10000条记录,然后合并排序,再返回从10001条开始的10条记录。因为3个primary shard数据的_source的分数不一样,可能某一个primary shard中第一条数据都没有另外一个primary shard中的最后一条分数都高。这样取数据可能不正确。
- 问题解决:采用scroll query。
- 性能问题:
- 耗费网络带宽:如果搜索过深,各个shard要把数据传送给协调节点(coordinate node),这个过程要有大量数据传递和网络消耗。
- 消费内存:各个shard要把数据转送给协调节点(coordinate node),这个传递回来的数据,要被协调节点保存到内存,消耗大量内存。
- 消耗cpu:node要把传递回来的数据进行排序,排序过程大量消耗cpu。
- 注意点:
- 当数据超过1w。
- 返回结果不要超过1000,500以下为宜。
测试数据样例
PUT /product/_doc/1
{
"name" : "xiaomi phone",
"desc" : "shouji zhong de zhandouji",
"price" : 3999,
"tags": [ "xingjiabi", "fashao", "buka" ]
}
PUT /product/_doc/2
{
"name" : "xiaomi nfc phone",
"desc" : "zhichi quangongneng nfc,shouji zhong de jianjiji",
"price" : 4999,
"tags": [ "xingjiabi", "fashao", "gongjiaoka" ]
}
PUT /product/_doc/3
{
"name" : "nfc phone",
"desc" : "shouji zhong de hongzhaji",
"price" : 2999,
"tags": [ "xingjiabi", "fashao", "menjinka" ]
}
PUT /product/_doc/4
{
"name" : "xiaomi erji",
"desc" : "erji zhong de huangmenji",
"price" : 999,
"tags": [ "low", "bufangshui", "yinzhicha" ]
}
PUT /product/_doc/5
{
"name" : "hongmi erji",
"desc" : "erji zhong de kendeji",
"price" : 399,
"tags": [ "lowbee", "xuhangduan", "zhiliangx" ]
}