ElasticSearch Query DSL(一)

ElasticSearch Query DSL(一)

ElasticSearch提供了一个基于JSON的完整的Query DSL(Domain Special Language领域特定语言)。将查询 DSL 视为查询的 AST(抽象语法树),由两种类型的子句组成:

  • 简单的查询子句:简单查询子句在特定的字段上寻找特定的值。例如match、term、range。这些查询可以单独使用
  • 复合查询的子句:复合查询包含简单查询和复合查询并且以逻辑的方式组合多个查询(例如bool或者dis_max查询),或者改变他们的行为(例如constant_score查询)

查询子句的行为取决于它们是在查询上下文中还是在过滤器上下文中使用。

查询和过滤器上下文

相关性分数

默认情况下,ElasticSearch通过相关性分数对匹配的结果进行排序,相关性分数衡量了每个文档与查询的匹配程度。

相关性分数是一个正浮点数,在search API中以_score字段返回。_score分数越高,说明文档的相关性越高。虽然每种查询类型可以计算出不同的相关性分数,但是分数计算也取决于查询子句是在查询上下文中还是在过滤器上下文中。

查询上下文

在查询上下文中,一个查询回答了此文档与此查询子句的匹配程度如何?的问题。除了决定文档是否匹配之外,查询上下文还会计算_score相关性分数。

查询上下文将查询子句传递给query参数时开始生效,例如search API中的query参数。

过滤器上下文

在过滤器上下文中,回答的是这个文档匹配这个查询子句么?的问题,这个回答只是简单的yes or no_score相关性分数不会被计算。过滤器上下文大多数情况下用来过滤结构化数据,例如:

  • 这个timestamp是否在20152016之间
  • status字段是否是pushlished

ElasticSearch会自动缓冲常用的过滤器,来提高查询性能。

查询和过滤器上下文使用示例

以下是在search API中使用查询和过滤器上下文中使用查询子句的例子。这个查询将根据以下条件来匹配文档

  • title字段包含search单词
  • content字段包含elasticsearch单词
  • status字段包含精确的pushlished
  • publish_date 字段包含从 2015 年 1 月 1 日起的日期。
curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": { 
    "bool": { 
      "must": [
        { "match": { "title":   "Search"        }},
        { "match": { "content": "Elasticsearch" }}
      ],
      "filter": [ 
        { "term":  { "status": "published" }},
        { "range": { "publish_date": { "gte": "2015-01-01" }}}
      ]
    }
  }
}
'

复合查询

Boolean查询

与其他boolean查询相结合的匹配查询。bool查询对应LucenceBooleanQuery。它使用一个或者多个boolean子句构建,每个子句都有一个类型化事件,事件类型是:

must该子句必须出现在匹配的文档中。这将有助于计算得分。利用逻辑语句替换其实就是and关系
filter该子句必须出现在匹配的文档中。然后不像是must那样,分数计算将被忽略。过滤器查询在过滤器上下文中执行,这意味着忽略评分并考虑将子句用于缓存。
should这个子句应该出现在匹配的文档中。利用逻辑语句替换其实就是or的关系。
must_not该子句一定不能出现在匹配的文档中。子句在过滤器上下文中执行,这意味着忽略评分并考虑将子句用于缓存。由于评分被忽略,所有文档的评分为 0。

bool查询采用越多越好的方法,因此每个匹配到的mustshould子句得分将被加在一起,作为每个文档的最终_score

curl -X POST "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "bool" : {
      "must" : {
        "term" : { "user.id" : "kimchy" }
      },
      "filter": {
        "term" : { "tags" : "production" }
      },
      "must_not" : {
        "range" : {
          "age" : { "gte" : 10, "lte" : 20 }
        }
      },
      "should" : [
        { "term" : { "tags" : "env1" } },
        { "term" : { "tags" : "deployed" } }
      ],
      "minimum_should_match" : 1,
      "boost" : 1.0
    }
  }
}
'
使用minimum_should_match

你可以使用minimum_should_match参数来指定mush子句匹配到的文档中should子句的数量或者百分比。

如果bool查询包含最少一个should子句并且没有must或者filter子句,那么默认值为1,否则为0

使用bool.filter计算分数

filter元素下的查询对评分没有影响,_score会返回0。例如,以下所有三个查询都返回状态字段包含术语 active 的所有文档。

第一个查询为所有文档分配 0 分,因为没有指定评分查询:

curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "bool": {
      "filter": {
        "term": {
          "status": "active"
        }
      }
    }
  }
}
'

这个 bool 查询有一个 match_all 查询,它为所有文档分配 1.0 的分数。

curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "term": {
          "status": "active"
        }
      }
    }
  }
}
'

这个 constant_score 查询的行为方式与上面的第二个示例完全相同。 constant_score 查询将 1.0 的分数分配给过滤器匹配的所有文档。

curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "status": "active"
        }
      }
    }
  }
}
'

提升查询

返回positive查询匹配到的文档,同时降低negative查询匹配的文档的相关性分数。

你可以使用boosting查询来降级某些文档而不将他们从搜索结果中排除。

请求例子
curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "boosting": {
      "positive": {
        "term": {
          "text": "apple"
        }
      },
      "negative": {
        "term": {
          "text": "pie tart fruit crumble tree"
        }
      },
      "negative_boost": 0.5
    }
  }
}
'
boosting的顶级参数
  • positive:(必须,查询对象),希望运行的查询。任何返回的文档都必须以此查询相匹配。
  • negative:(必须,查询对象),降低匹配到文档的相关性分数的查询。如果返回的文档与boosting查询和此查询匹配,则提升查询将计算文档的最终相关性分数,如下所示:
    • positive查询中获取原始相关性分数。
    • 将分数乘以negative_boost 值。
  • negative_boost:(必须,float),0 到 1.0 之间的浮点数用于降低与negative查询匹配的文档的相关性分数。

常量得分查询

包装一个过滤器查询并且返回与boost参数值相等的匹配文档。

curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "constant_score": {
      "filter": {
        "term": { "user.id": "kimchy" }
      },
      "boost": 1.2
    }
  }
}
'

全文查询

全文查询允许你搜索已经被分析的文本字段,例如邮件的正文。

间隔查询

intervals查询使用匹配规则。然后将这些规则应用于来自指定字段的术语。

这些定义产生跨越文本主体中的术语的最小间隔序列。这些间隔可以通过父源进一步组合和过滤。

例如,我们用my favourite food这样一个字符串在my_text field里进行intervals查询,查询规则是该字符串出现在"hot water"或者cold porridge字符串的前面,那么query语句可以这样来写:

curl -X POST "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "intervals" : {
      "my_text" : {
        "all_of" : {
          "ordered" : true,
          "intervals" : [
            {
              "match" : {
                "query" : "my favorite food",
                "max_gaps" : 0,
                "ordered" : true
              }
            },
            {
              "any_of" : {
                "intervals" : [
                  { "match" : { "query" : "hot water" } },
                  { "match" : { "query" : "cold porridge" } }
                ]
              }
            }
          ]
        }
      }
    }
  }
}
'

简要概述上面语句,像包含my favourite food is cold porridge这样字符串的文档就会被检索到,因为my favourite food出现在cold porridge前面,满足intervals query语法规则;另一个只包含了when it's cold my favourite food is porridge字符串的文档就不会被匹配到,因为coldporridge出现在了my favourite food两边,不符合我们配置的intervals query语法规则。

match参数
参数描述
query用户查询的字符串
max_gaps字符串中每个词在text field中出现的最大词间距,超过最大间距的将不会被检索到;默认值是-1,即不限制,设置为0的话,query中的字符串必须彼此相连不能拆分
orderedquery中的字符串是否需要有序显示,默认值是false,即不考虑先后顺序
analyzer对query参数中的字符串使用什么分词器,默认使用mapping时该field配置的 search analyzer
filter可以为query搭配一个intervals filter,该filter不同于Boolean filter 有自己的语法结构
all_of参数
参数描述
intervals一个interval集合,集合里面的所有match需要同时在一个文档数据上同时满足才行
max_gaps多个interval查询在一个文档中允许的最大间距,超过最大间距的将不会被检索到;默认值是-1,即不限制,设置为0的话,所有的interval query必须彼此相连不能拆分
ordered配置 intervals 出现的先后顺序,默认值false
filter可以为query搭配一个intervals filter,该filter不同于Boolean filter 有自己的语法结构
any_of参数
参数描述
intervals一个interval集合,集合里面的所有match不需要同时在一个文档数据上同时满足
filter可以为query搭配一个intervals filter
filter参数

match query filter,不是严格的查询过滤器,不同于Boolean filter ,有自己的语法结构.我们先看一个例子,假设我们要在my_text field上查询包含hotporridge的文档,要求这两个词的词距不超过10个字符,且文档中不包含salty,以下是查询语句:

curl -X POST "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "intervals" : {
      "my_text" : {
        "match" : {
          "query" : "hot porridge",
          "max_gaps" : 10,
          "filter" : {
            "not_containing" : {
              "match" : {
                "query" : "salty"
              }
            }
          }
        }
      }
    }
  }
}
'
参数描述
containinginterval query中terms之间需要包含filter中的terms
contained_byinterval query中的字符串需要被包含在filter query的terms里
not_containingcontaining 对立面
not_contained_bycontained_by 对立面包
not_overlappingquery 与filter 词距不重叠

匹配查询

返回与提供的文本、数值、日期或者布尔值相匹配的文档。这个提供的文本在匹配前会被分析。

例子如下:

curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "message": {
        "query": "this is a test"
      }
    }
  }
}
'
match的顶级参数
  • <field>:(必须,对象),你希望搜索的字段名
field参数
  • query:(必须),你希望在提供的<field>字段中查找文本,数值,日期或者布尔数据。

    match在执行查询之前会分析提供的任何文本数据。这意味着匹配查询可以在文本字段中搜索分析的分词而不是精确的术语。

  • analyzer:(可选的,字符串),analyzer从来将查询值中的文本数据转换为分词。默认为 <field> 映射的索引时间分析器。如果没有映射分析器,则使用索引的默认分析器。

  • auto_generate_synonyms_phrase_query:(可选的,boolean),如果为truematch phrase自动为多个术语创建同义词。默认为true

  • fuzziness:(可选的,string),允许匹配的最大编辑距离

  • max_expansions:(可选的,integer),查询将扩展到的最大术语数。默认值为50。

  • prefix_length:(可选的,integer),模糊匹配的起始字符数。默认值为0。

  • fuzzy_transpositions:(可选的,boolean),如果为真,则模糊匹配的编辑包括两个相邻字符的换位(ab→ba)。默认值为true

  • operator:(可选的。字符串)布尔逻辑,用于解释查询值中的文本。有效值:

    • OR (Default)capital of Hungary>>>>>> capital OR of OR Hungary.
    • ANDcapital of Hungary >>>>> capital AND of AND Hungary.
短请求例子

您可以通过组合 <field> 和查询参数来简化匹配查询语法。例如:

curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "message": "this is a test"
    }
  }
}
'

匹配布尔前缀查询

match_bool_prefix查询分析其输入,并从术语构造一个bool查询。除了最后一个术语外,其他每个术语都将在术语查询中使用。最后一个词用于前缀查询。match_bool_prefix查询,例如

curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match_bool_prefix" : {
      "message" : "quick brown f"
    }
  }
}
'

其中分析产生的术语 quickbrownf 类似于以下 bool 查询

curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "bool" : {
      "should": [
        { "term": { "message": "quick" }},
        { "term": { "message": "brown" }},
        { "prefix": { "message": "f"}}
      ]
    }
  }
}
'

match_bool_prefix查询和match_phrase_prefix查询的一个重要区别是,match_phrase_prefix查询以短语的形式匹配它的词汇,但是match_bool_prefix查询可以在任何位置匹配它的词汇。上面的示例match_bool_prefix查询可以匹配包含quick brown fox的字段,但是也可以匹配brown fox quick。它还可以匹配包含术语quick、术语brown和以f开头的术语的字段,这些术语出现在任何位置。

参数

默认情况下,match_bool_prefix查询的输入文本将使用来自查询字段映射的分析器进行分析。可以使用分析器参数配置不同的搜索分析器

curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match_bool_prefix": {
      "message": {
        "query": "quick brown f",
        "analyzer": "keyword"
      }
    }
  }
}
'

匹配短语查询

match_phrase查询分析文本,并从分析文本中创建一个短语查询。例如:

curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match_phrase": {
      "message": "this is a test"
    }
  }
}
'

可以将分析器设置为控制哪个分析器将对文本执行分析过程。它默认为字段显式映射定义,或默认搜索分析器,例如:

curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match_phrase": {
      "message": {
        "query": "this is a test",
        "analyzer": "my_analyzer"
      }
    }
  }
}
'

组合字段

combined_fields查询支持搜索多个文本字段,就好像它们的内容已被索引到一个组合字段中一样。它采用以术语为中心的查询视图:首先将查询字符串分析为单独的术语,然后在任何字段中查找每个术语。当匹配可以跨越多个文本字段时,此查询特别有用,例如文章的titleabstractbody

curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "combined_fields" : {
      "query":      "database systems",
      "fields":     [ "title", "abstract", "body"],
      "operator":   "and"
    }
  }
}
'

提示:一次可以查询的字段数是有限制的。 默认为 1024。它由indices.query.bool.max_clause_count设置。

字段提升

可以使用脱字符 (^) 符号提升单个字段:

curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "combined_fields" : {
      "query" : "distributed consensus",
      "fields" : [ "title^2", "body" ] 
    }
  }
}
'

combined_fields查询提供了一种跨多个文本字段进行匹配和评分的原则方法。为了支持这一点,它要求所有字段具有相同的搜索分析器。

如果您希望使用单个查询来处理不同类型的字段,如关键字或数字,那么multi_match查询可能更适合。它同时支持文本和非文本字段,并接受不共享同一分析器的文本字段。

主要的multi_match匹配模式best_fieldsmost_fields采用以字段为中心的查询视图。相反,combined_fields是以术语为中心的:operatorminimum_should_match是按术语而不是按字段应用的。具体地说,类似于:

curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "combined_fields" : {
      "query":      "database systems",
      "fields":     [ "title", "abstract"],
      "operator":   "and"
    }
  }
}
'
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值