Elasticsearch Query DSL

1. 序

Hive 无疑是数据相关工作最常用的的工具,利用 SQL 就能够完成许多统计和分析的任务,学习成本低,开发效率高。

但是 Hive 的缺点也很明显:运行慢!所以 Hive 一般用来做离线计算,每天由调度系统调用脚本完成一系列的计算任务,产出数据然后交给其他应用展现。但总有一些情景是 Hive 满足不了的,比如对数据的实时查询,比如对数据的快速分析。

这个时候就可以使用我们今天要介绍的工具:Elasticsearch。

2. 简介

ElasticSearch 是一种基于 Apache Lucene 的开源项目,主要面向的是数据的实时检索、分析以及全文搜索等。

Elasticsearch 的几个特性非常棒:
1. RESTful API,使用 Json 交换数据
2. 跨 index 的查询
3. 速度,尤其是大数据量下聚合函数的速度非常快!

3. Query DSL

我们可以使用两种结构化语句: 结构化查询(Query DSL)和结构化过滤(Filter DSL)。 查询与过滤语句非常相似,但是它们由于使用目的不同而稍有差异。
一条过滤语句会询问每个文档的字段值是否包含着特定值,一条查询语句会计算每个文档与查询语句的相关性,会给出一个相关性评分 _score,并且 按照相关性对匹配到的文档进行排序。

3.1 term 过滤

精确匹配数字、日期、布尔值或 not_analyzed 的字符串。相当于等号 =

{ "term": { "age":    26           }}
{ "term": { "date":   "2014-09-01" }}
{ "term": { "public": true         }}
{ "term": { "tag":    "full_text"  }}

3.2 terms 过滤

精确匹配多个值。相当于 in

{
    "terms": {
        "tag": [ "search", "full_text", "nosql" ]
    }
}

3.3 range 过滤

按照指定范围查找一批数据,相当于 between

{
    "range": {
        "age": {
            "gte":  20,
            "lt":   30
        }
    }
}
字段 含义
gt >
gte >=
lt <
lte <=

3.4 existsmissing 过滤

针对已经查出一批数据,但是想区分是否存在某个字段。类似于 IS_NULL 条件。

{
    "exists": {
        "field": "title"
    }
}

3.5 bool 过滤

bool 过滤可以用来合并多个过滤条件查询结果的布尔逻辑:

过滤子句 含义
must 多个查询条件完全匹配,相当于 and
must_not 多个查询条件的相反匹配,相当于 not
should 至少有一个查询条件匹配,相当于 or

复合实例:

{
    "bool": {
        "must": { "term": { "folder": "inbox" }},
        "must_not": { "term": { "tag": "spam" }},
        "should": [
            { "term": { "starred": true }},
            { "term": { "unread":  true }}
        ]
    }
}

3.6 match_all 查询

使用 match_all 可以查询到所有文档,事没有查询条件下的默认语句。

{
    "query": {
        "match_all": {}
    }
}

此查询常用于合并过滤条件。比如说你需要检索所有的邮箱,所有的文档相关性都是相同的,所以得到的 _score 为 1。

3.7 match 查询

某个字段中包含特定内容

{
    "query": {
        "match": {
            "字段名": "特定内容"
        }
    }
}

如果用 match 指定了一个确切值,在遇到数字,日期,布尔值或者 not_analyzed 的字符串时,它将为你搜索你给定的值:

{ "match": { "age":    26           }}
{ "match": { "date":   "2014-09-01" }}
{ "match": { "public": true         }}
{ "match": { "tag":    "full_text"  }}

3.8 multi_match 查询

multi_match 查询允许你在 match 查询的基础上同时搜索多个字段:

{
    "multi_match": {
        "query":    "full text search",
        "fields":   [ "title", "body" ]
    }
}

3.9 bool 查询

bool 查询与 bool 过滤相似,用于合并多个查询子句。不同的是,bool 过滤可以直接给出是否匹配成功,而 bool 查询要计算每一个查询子句的 _score (相关性分值)。

查询子句 含义
must 查询指定文档一定要被包含。
must_not 查询指定文档一定不要被包含。
should 查询指定文档,有则可以为文档相关性加分。

如果 bool 查询下没有 must 子句,那至少应该有一个 should 子句。但是 如果有 must 子句,那么没有 should 子句也可以进行查询。

4. 查询与过滤条件的合并

search API 中只能包含 query 语句,所以我们需要用 filtered 来同时包含 queryfilter 子句,外面再包含一层 query

{
    "query": {
        "filtered": {
            "query":  { "match": { "email": "business opportunity" }},
            "filter": { "term":  { "folder": "inbox" }}
        }
    }
}

5. 验证查询

5.1 验证

validate API 可以验证查询语句是否合法:

curl -XGET 'http://dp.diditaxi.com.cn:80/es/<INDEX>/<TYPE>/_validate/query?pretty=true' -d '{
    QUERY
}'

返回结果:

#合法
{
  "valid" : true,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  }
}

#非法
{ 
    "valid" :         false, 
    "_shards" : {    
        "total" :       1,    
        "successful" :  1,    
        "failed" :      0  
    }
 }

5.2 理解错误信息

想知道语句非法的具体错误信息,需要加上 explain 参数:

curl -XGET 'http://dp.diditaxi.com.cn:80/es/<INDEX>/<TYPE>/_validate/query?explain&pretty=true' -d '{
    QUERY
}'

发表评论

电子邮件地址不会被公开。 必填项已用*标注