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 exists
和 missing
过滤
针对已经查出一批数据,但是想区分是否存在某个字段。类似于 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
来同时包含 query
和 filter
子句,外面再包含一层 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
}'