"ES提供了基于JSON的查询DSL,它由两种语句组成:
- 叶子查询(Leaf Query):查询特定字段的特定值,比如
match
,term
,range
查询,这些查询可以单独使用。 - 复合查询(Compound Query):复合查询包装其他叶子查询和复合查询,以逻辑运算的方式(比如
bool
,dis_max
查询)连接多个查询,或更改它们的行为(比如,constant_score
查询)
依据它们是在查询上下文(query context)还是过滤上下文(filter context),查询语句的行为也有所不同。
查询和过滤上下文
查询上下文
在查询上下文解决的是这种问题:“此文档与此查询的匹配程度如何?”,除了决定文档是否匹配外,查询语句还会计算一个_score
字段,表示该文档相对其他文档的匹配程度。
位于query
参数下的语句,处于查询上下文。
过滤查询
过滤上下文解决的是这种问题:“此文档是否匹配该查询”,回答只有是或者否,不会计算相关性分值。过滤上下文主要用于过滤结构化的数据,比如:
- 这个时间是否属于2015-2016年之间
- status字段的值是否是
1
ES会缓存经常使用的查询,以提升性能。
位于filter
参数下的语句,处于过滤上下文中。比如在bool
查询中的filter
或must_not
参数,在constant_score
查询中的filter
参数,或filter
聚合。
下面的示例展示搜索API中,在查询上下文和过滤上下文中的语句。这条查询会匹配满足下列条件的文档:
title
字段包含单词search
content
字段包含单词elasticsearch
satus
字段指就是published
publish_date
字段的日期大于等于2015.1.1
GET /_search
{
"query": {
// 查询上下文
"bool": {
"must":[
{
"match": {
"title": "search"}},
{
"match": {
"content": "elasticsearch"}}
],
"filter":[ // 过滤上下文
{
"term": {
"status": "published"}},
{
"range": {
"publish_data": {
"gte": "2015-01-01"}}}
]
}
}
}
说明:
bool
和match
语句用在查询上下文中,这意味着他们被用来评估每个文档的匹配程度(分值)。term
和range
语句用在过滤上下文中,它们会过滤掉不匹配的文档,但是不会影响匹配文档的分值
匹配所有
match_all
查询,匹配所有文档,每个文档_score
值为1:
GET {
index}/_search
{
"query": {
"match_all": {
}
}
}
与之相反的是match_none
,不匹配任何文档
全文查询
全文查询允许你搜索分词后的文本字段,比如电子邮件的内容。包括:
match
:全文查询的标准方式,包括模糊匹配(fuzzing),短语或邻近查询。match_phrase
:类似match
,但只用于精确匹配短语或单词邻近匹配match_phrase_prefix
:同上,但是只对最后一个单词进行通配符搜索match_bool_prefix
:创建一个bool查询,对每个词条创建一个term
查询,最后一个词条除外,该词条作为prefix
查询匹配multi_match
:match
查询的多字段形式common
词条查询:相对专门的查询,适用于不常用的单词query_string
查询:支持紧凑的Lucene查询字符串语法,支持在单个查询字符串中指定AND|OR|NOT
逻辑条件和多字段搜索。仅限专业用户使用simple_query_string
查询:比起query_string
语法更简单,更健壮,适用于普通用户使用intervals
查询:允许对匹配词条的顺序和邻近度进行细粒度(fine-grained)的控制
match
我们先创建一条文档:
POST twitter/_doc
{
"user": "ayhan",
"post_date": "2009-11-15T14:12:12",
"message": "let me out from here"
}
基本用法:
GET twitter/_search
{
"query": {
"match": {
"message": "out me" // messag是搜索的字段,值是要查询的字符串
}
}
}
因此上述查询的结果是message字段中包含词条out, 或me的所有文档。
match查询会对提供的文本进行分词,并构建布尔查询。逻辑运算符operator
默认是or
,我们也可以手动设为and
,来控制布尔语句。
GET twitter/_search
{
"query": {
"match": {
"message": {
"query": "out me", // 指定查询字符串
"operator": "and" // 指定逻辑运算符
}
}
}
}
这样查询的结果是message字段中同时包含词条out 和 me的所有文档,范围将大大缩小。
除了指定operator
,我们还可以指定如下参数:
analyzer
指定分词器minimum_should_match
,没看懂lenient
:异常处理,是否忽略由数据类型错误导致的异常,默认false
,比如使用文本查询字符串来查询数字字段zero_terms_query
:零项查询,指定查询词条为空时的行为(比如指定的分词器移除了所有词条),其值为:none
,相当于match_none
,默认值all
,相当于match_all
cutoff frequency
:指定文档高低频的分界线synonyms
对于同义词定义:ny, new york
,相当于ny OR (new york)
match phrase
短语匹配,示例:
GET twitter/_search
{
"query": {
"match_phrase": {
"message": "huawei mate pro" // 查询message字段包含huawei mate pro的文档
}
}
}
类似match查询,短语匹配首先也会将查询字符串解析为词条列表,然后对这些词条进行搜索。但是只保留同时包含所有词条,且位置顺序与搜索词条一致,中间不夹杂其他单词的文档。
短语匹配是利用倒排索引中的位置信息实现的。
判断文档是否和短语huawei mate pro
匹配,要同时满足如下条件:
huawei
、mate
和pro
必须全部出现mate
的位置比huawei
大1pro
的位置比mate
大2
multi_match
multi_match基于match查询,但是支持查询多个字段:
GET article/_search
{
"query": {
"multi_match": {
"query": "hello world", // 查询字符串
"fields": ["title", "content"]