Elasticsearch 之Search API

search api 概览

  • search api 实现对es中存储的数据进行查询分析,endpoint为 _search,
//对所有索引查询
GET /_search
//指定单个索引查询
GET /my_index/_search
//指定索引查询,一次可查多个
GET /my_index1,my_index2/_search
GET /my_*/_search
  • 查询主要有两种形式
    (1)URI Search :操作简便,方便通过命令行测试;仅包含部分查询语法

    GET /my_index/_search?q=user:tom
    

    (2)Request Body Search:es 提供的完备查询语法 Query DSL(Domain Specific Language)

    GET /my_index/_search
    {
      "query":{
         "term":{
            "user": "tom"
         }
      }
    }
    

uri search 详解

  • 通过url query 参数来实现搜索,常用参数如下:
    q 制定查询的语句,语法为 Query String Synax
    df q中不指定字段时,默认查询的字段,如果不指定,es 会查询所有字段
    sort 排序
    timeout 指定超时时间,默认不超时
    from, size 用于分页
    例如:查询username字段包含tom的文档,结果按照age升序排列,返回第5~14个文档,如果超过1s没有结束,则以超时结束
GET /my_index/_search?q=tom&df=username&sort=age:asc&from=4&size=10&timeout=1s
{
 "profile": true  //查询语句调优
}

term 与 phrase

例如:
hello word 【等效于查询 hello 或 word 两个单词】
“hello word” 【查询词语,要求先后顺序】

  • 泛查询
    例如:tom 【等效于在所有字段中去匹配该 term】
  • 指定字段
    例如:username: tom
  • Group 分组设定,使用括号指定匹配的规则
    例如:
    (quick OR brown) AND fox 【在所有字段里查询一定有fox 并且还有quick或brown 的文档】
    status:(active OR pending) title:(full text search) 【查询status字段包括active或pending title字段包括full 或 text 或search】

布尔操作符

  • AND(&&), OR(||), NOT(!)
    例如:
    name:(tom NOT lee) 【注意大写,不能小写】
    name:((lee && !alfred) || (tom && lee && !alfred))
  • ”+“ ” -“ 分别对应 must 和 must_not
    例如:name:(tom -alfred) +lee
  • ”+“ 在url()中会被解析为空格,要使用encode后的结果才可以,为%2B
    例如:name:(tom %2Balfred)

范围查询,支持数值和日期

  • 区间写法,闭区间用 [], 开区间用 {}
    例如:
    age:[1 TO 10] 意为 1<=age<=10
    age:[1 TO 10} 意为 1<=age<10
    age:[1 TO ] 意为 age>=1
    age:[* TO 10] 意为 age<=10
  • 算数符号写法
    例如:
    age:>=1
    age:(>=1&&<=10) 或者 age:(+>=1 +<=10)

通配符查询

  • ?代表1个字符,* 代表0或者多个字符
    例如:
    name:t?m
    name:tom*
    name:t*m
  • 通配符匹配执行效率低,且占用较多内存,不建议使用;无特殊要求,不要将?/* 放在最前面
  • 正则表达式 ,也不建议使用,吃内存
    例如: name:/[mb]oat/
  • 模糊匹配 fuzzy query
    例如:name:roam~1 【匹配与roam差一个字符的词】
  • 近似度查询 proximity search
    例如:“fox quick”~5 【以单词为单位进行差异比较,比如”quick fox “ "quick brown fox"都会被匹配】

request body search

  • request body search 将查询语句通过 http request body 发送到 es,主要包括如下参数
    query 符合 Query DEL 语法的查询语句
    from,size
    sort 等
GET /my_index/_search
{
  "query":{
     "term":{"username": "tom"}
  }
}
  • Query DSL
    基于JSON定义的查询语言,主要包括如下两种类型:
    (1)字段类查询:如term,match,range等,只针对某一个字段进行查询
    (2)复合查询:如bool查询等,包含一个或多个字段类查询或者复合查询语句

字段类查询

字段类查询主要包括以下两类

  • 全文匹配:针对text类型的字段进行全文检索,会对查询语句先进行分词处理,如 match,match_phrase 等 query 类型
    (1)Match Query 对字段做全文检索,最基础和常用的查询类型,API示例如下:

    GET my_index/_search
    {
      "profile": true
      "query":{
         "match":{ //关键词
            "username": "tom lee" //查询username字段有 tom或者lee的
         }
      }
    }
    

    match query 流程
    在这里插入图片描述
    通过operator 参数可以控制单词间的匹配关系,可选项为 or 和 and

    GET my_index/_search
    	{
    	  "profile": true
    	  "query":{
    	     "match":{ //关键词
    	        "username": {
    	          "query": "tom lee",
    	          "operator": "and"
    	        } 
    	     }
    	  }
    	}
    

    通过 minimum_should_match 参数可以控制需要匹配的单词数

    GET my_index/_search
    	{
    	  "profile": true
    	  "query":{
    	     "match":{ //关键词
    	        "username": {
    	          "query": "php ruby engineer",
    	          "minimum_should_match ": "2" //上面查询语句有2个单词符合就查询出
    	        } 
    	     }
    	  }
    	}
    

    (2)Match Phrase Query 对字段做检索,有顺序要求,API示例如下:

    GET my_index/_search
    {
      "profile": true
      "query":{
         "match_phrase":{ //关键词
            "job": "php engineer" //只能查到php单词在engineer之前的
         }
      }
    }
    

    通过 slop 参数可以控制单词间的间隔

    GET my_index/_search
    	{
    	  "profile": true
    	  "query":{
    	     "match_phrase":{ //关键词
    	        "job": {
    	          "query": "php engineer",
    	          "slop ": "1" //上面查询单词间允许有1个单词的差异
    	        } 
    	     }
    	  }
    	}
    

    (3)Query String Query 类似于URI Search 中的q参数查询 ,API示例如下:

    GET my_index/_search
    {
      "query":{
         "query_string":{ //关键词
            "default_field":"job", //指明默认查询的字段名
            "query": "php engineer" 
         }
      }
    }
    
  • 单词匹配:不会对查询语句做分词处理,直接去匹配字段的倒排索引,如 term,terms,range 等 query 类型
    (1)TermQuery 将查询语句作为整个单词进行查询,不会对查询语句做分词处理,API示例如下:

    GET my_index/_search
    {
      "profile": true
      "query":{
         "term":{ //关键词
            "username": "tom lee" //查询username字段有"tom lee"的
         }
      }
    }
    

    (2)TermsQuery 一次传入多个单词进行查询, API示例如下:

    GET my_index/_search
    	{
    	  "profile": true
    	  "query":{
    	     "terms":{ //关键词
    	        "username":[ "tom", "lee"] 
    	     }
    	  }
    	}
    

    (3)RangeQuery 范围查询主要针对数值和日期类型, API示例如下:

    GET my_index/_search
    	{
    	  "query":{
    	     "range":{ //关键词
    	        "age":{
    	          "gte": 10,
    	          "lte": 20
    	        }
    	     }
    	  }
    	}
    

    RangeQuery - Date Math 针对日期提供的一种更友好的计算方式,格式如下:
    now - 1d 【now: 基准日期,也可以是具体的日期,比如2020-03-04,使用具体日期的时候要用||做分隔;- 1d : 计算公式,主要有如下3种:+1h - 加一小时、-1d - 减一天、/d - 将时间舍入到天】
    单位主要有如下几种: y(years)、M(months)、w(weeks)、d(days)、h(hours)、m(minutes)、s(seconds)

复合查询

复合型查询是指包含字段类查询或复合查询的类型,主要包括一下几类:
constant_score query、bool query、dis_max query、function_score query、boosting query
(1)constant_score query 该查询将其内部的查询结果文档得分都设定为1或者boost的指;多用于结合bool查询实现自定义得分

GET my_index/_search
	{
	  "query":{
	     "constant_score":{ //关键词
	        "filter":{ //只能有一个
	          "match":{
	            "username":"alfred"
	          }
	        }
	       
	     }
	  }
	}

(2)bool query 该查询有一个或者多个布尔子句组成,主要包括如下4个:

参数含义
filter只过滤符合条件的文档,不计算相关性得分
must是数组,文档必须符合must中的所有条件,会影响相关性得分
must_not文档必须不符合must_not 中的所有条件
should文档可以符合should中的所有条件,会影响相关性得分

API示例如下:

GET my_index/_search
	{
	  "query":{
	     "bool":{ //关键词
	        "filter":[
	          {}
	          ],
	       "must":[
	          {}
	          ],
	        "must_not":[
	          {}
	          ],
	        "should":[
	          {}
	          ]
	        }
	     }
	  }
	}

== filter:es针对filter会有智能缓存,因此其执行效率很高;做简单匹配查询且不考虑算分时,推荐使用filter代替query ==

GET my_index/_search
	{
	  "query":{
	     "bool":{ //关键词
	        "filter":[{ 
	          "term":{
	            "username":"alfred"
	          }
	        }]
	       
	     }
	  }
	}

** must ** 查询username包含alfred并且job包含php关键词的文档列表

GET my_index/_search
	{
	  "query":{
	     "bool":{ //关键词
	        "must":[ //2个match query 文档最终的得分为这两个查询的得分加和
		        { 
		          "match":{
		            "username":"alfred"
		          }
		        },
		        { 
		          "match":{
		            "job":"php"
		          }
		        }
	        ]
	       
	     }
	  }
	}

** should** 使用分两种情况:
bool查询中只包含should,不包含must,文档必须满足至少一个条件
minimum_should_match 可以控制满足条件的个数或者百分比

GET my_index/_search
	{
	  "query":{
	     "bool":{ //关键词
	        "should":[ 
		        { 
		          "term":{
		            "job":"ruby"
		          }
		        },
		        { 
		          "term":{
		            "job":"php"
		          }
		        }, 
		        { 
		          "term":{
		            "job":"java"
		          }
		        }
	        ],
	       "minimum_should_match":2 //以上条件至少满足2个
	     }
	  }
	}

bool同时包含should和must时,文档不必满足should的条件,但是如果满足了,会增加相关性得分

GET my_index/_search
	{
	  "query":{
	     "bool":{ //关键词
	        "should":[ 
		        { 
		          "term":{
		            "job":"ruby"
		          }
		        }
	        ],
	        "must":[ 
		        { 
		          "term":{
		            "username":"tom"
		          }
		        }
	        ]
	     }
	  }
	}

(3)query context 与 filter context 的区别:当一个查询语句位于query或者filter 上下文时,es 执行的结果会不同,对比如下:

上下文类型执行类型使用方式
Query查找与查询语句最匹配的文档,对所有文档进行相关性算分并排序query;bool中的 must 和 should
Filter查找与查询语句相匹配的文档bool中的 filter 和 must_not;constant_score中的filter
GET my_index/_search
	{
	  "query":{
	     "bool":{ //关键词
	        "must":[  //会算分查询
		        { 
		          "term":{
		            "username":"tom"
		          }
		        }
	        ],
	         "filter":[  //不算分查询
	            {
	              "range":{
	                 "create_time":{"gte":2020-02-01}
	              }
	            }
	         ]
	     },
	    
	  }
	}

Count API

获取符合条件的文档数,endpoint为 _count
在这里插入图片描述

Source Filtering

过滤返回结果中_source中的字段,主要有如下几种方式:

GET /test_index/_search?_source=username //url参数

GET /test_index/_search
{
 "_source":false  //不返回 _source
}

GET /test_index/_search
{
 "_source":["username","job"]  //返回 部分字段
}

GET /test_index/_search
{
 "_source":{
   "includes": "i*", //模糊匹配字段
   "escludes": "birth"
 } 
}

相关性算分

  • 相关性算分是指文档与查询语句间的相关度,英文为 relevance
    通过倒排索引可以获取与查询语句相匹配的文档列表,本质是一个排序问题,排序的依据是相关性算分

  • 相关性算分的几个重要概念如下:
    (1)Term Frequency(TF)词频,即单词在该文档中出现的次数。词频越高,相关性越高
    (2)Document Frequency(DF)文档频率,即单词出现的文档数
    (3)Inverse Document Frequency(IDF)逆向文档频率,与文档频率相反,即单词出现越少,相关度越高
    (4) Field-length Norm 文档越短,相关性越高

  • ES 目前主要有两个相关性算分模型,如下:
    (1)TF/IDF模型
    (2)BM25 模型 5.x之后的默认模型,相比TF/IDF的一大优化是降低了tf在过大时的权重

  • 可以通过explain参数来查看具体的计算方法,但要注意:

  • (1)es的算分是按照shard进行的,即shard的分数计算是相互独立的,所以使用explain的时候注意分片数

  • (2)可以通过设置索引的分片数为1来避免这个问题

    PUT test_search_index
    {
      "settings": {
        "index":{
          "number_of_shards": "1"
        }
      }
    }
    
    GET /test_search_index
    {
     "explain": true,
     "query":{
        "match":{
          "username":"alfred way"
        }
     }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值