Elasticsearch-查询表达式,elasticsearch-
查询表达式(QUERY DSL)是一种非常灵活又富有表现力的查询语言。Elasticsearch使用它可以以简单的JSON接口来展现搜索引擎功能的绝大部分。在你的应用中,你应该用它来编写你的查询语句。它可以使你的查询语句更灵活、更精确、易读和易调试。
要使用这种查询表达式,只需将查询条件传递给query参数:
{
"query":...
}
空查询,查询索引库中所有的文档:
{
}
等价于:
{
"query":{
"match_all":{}
}
}
查询语句的结构
一个简单的查询语句,它的结构是:
{
QUERY_NAME:{
ARGUMENT:VALUE,
ARGUMENT:VALUE,
...
}
}
如果是针对某个字段,它的结构如下:
{
QUERY_NAME:{
FIELD_NAME:{
ARGUMENT:VALUE,
ARGUMENT:VALUE,
...
}
}
}
举个栗子,你可以使用match查询语句来查询name包含张的所有数据:
{
"match":{
"name":"张"
}
}
完整的请求体如下:
{
"query":{
"match":{
"name":"张"
}
}
}
一些重要的查询
虽然Elasticsearch自带了很多的查询。但经常用到的就那么几个。接下来将介绍几个常用的查询:
match_all查询
match_all查询,为查询所有文档。在没有指定查询方式时,它是默认的查询:
{
"query":{
"match_all":{}
}
}
match查询
无论你在任何字段上进行的是全文搜索还是精确值查询,match查询是你可用的标准查询。如果你在一个全文字段上使用match查询,在执行查询前,它将用正确的分析器去分析查询字符串:
{
"query":{
"match":{
"name":"张"
}
}
}
multi_match查询
multi_match可以在多个字段上进行相同的match查询:
{
"multi_match":{
"query":"query info",
"fields":["name","addr"]
}
}
range查询
range查询出落在指定区间内的时间或数字:
{
"range":{
"age":{
"gte":18,
"lte":22
}
}
}
range查询相关区间运算符:
- gt:大于
- lt:小于
- gte:大于或等于
- lte:小于或等于
term查询
term查询被用于精确值匹配,这些精确值可能是数字、时间、布尔或者那些not analyzed的字符串:
{
"query":{
"term":{
"date":"2017-10-30"
}
}
}
term查询对于输入的文本不分析,所以它将给定的值进行精确查询。它查询那些精确匹配的值(包括大小写,重音和空格等方面的差异)
terms查询
terms查询和term查询一样,但它允许你指定多值进行匹配。如果这个字段包含了指定值的任何一个值,那么这个文档满足条件:
{
"query":{
"terms":{
"date":["2017-10-30","2017-10-31"]
}
}
}
exists和missing查询
exists用于查询字段存在的文档,而missing用于查询字段不存在的文档。这与MongoDB中exists=true或exists=fasle有这相同的特性:
{
"query":{
"exists":{
"field":"name"
}
}
}
上述栗子用于查询name字段存在的所有文档。
组合多查询
在现实的开发过程中,查询的需求往往没有那么简单,不可能只查询一个条件就能满足我们的需求,往往需要查询多个条件,同时满足或者满足其中一个或这两个条件才是我们所需要的。为了构建类似的高级查询,你需要有一种能将多查询组合成一个单一查询的方法。
你可以用bool查询来实现一系列需求。这种查询可以将多个查询组合在一起,成为用户自己所需要的bool查询,它接收一下参数:
- must:文档必须匹配这些条件才能被包含进来
- must_not:文档必须不匹配这些条件才能被包含进来
- should:如果满足这些语句中的任意语句,将增加
_score,否则将无任何影响 - filter:必须匹配,但它以不评分、过滤模式来进行
举个栗子:
{
"query":{
"bool":{
"must":{"match":{"name":"laowang"}},
"must_not":{"term":{"age":18}},
"should":[
{
"match":{
"addr":"广东"
}
},
{
"match":{
"addr":"广西"
}
}
]
}
}
}
匹配
name = laowang并且age != 18,并且addr=广东或者addr=广西的所有文档。如果文档满足should中的任一条件_score值将更高,排名将靠前。如果都满足,_score将会更高。排名更靠前
Elasticsearch默认是按照_score进行排序的,而_score的大小是根据文档的匹配程度来决定的,filter查询对查询到的所有文档不进行评分,即查询到的数据是无序的。bool也可以嵌套在filter中进行一个不评分的查询,如下所示:
{
"query":{
"bool":{
"must":{"match":{"name":"laowang"}},
"filter":{
"bool":{
"must":{"match":{"age":18}}
}
}
}
}
}
值得注意的是filter必须嵌套在bool或其他查询中,不可单独拿出来使用
验证查询语句是否合法
当我们执行一个很复杂的查询语句时,我们可以用validate-queryAPI来验证这个查询语句是否合法:
curl -XGET 'http://localhost:9200/csdn/blog/_validate/query' -d '
{
"query":{
"name":{
"match":"laowang"
}
}
}
'
将会返回如下信息:
{
"valid": false
}
valid为false表示,查询语句不合法。只有vaild信息是远远不够的,我们还需要知道错误的原因是什么?我们可以将explain参数添加到查询当中:
curl -XGET 'http://localhost:9200/csdn/blog/_validate/query?explain' -d '
{
'query':{
"name":{
"match":"laowang"
}
}
}
'
将返回如下信息:
{
"valid": false,
"error": "org.elasticsearch.common.ParsingException: no [query] registered for [name]"
}
错误信息告诉我们,Elasticsearch中没有name查询表达式。