详解Elasticsearch Query DSL
详解Elasticsearch Query DSL
Elasticsearch是目前的首选搜索、分析引擎,但要熟练掌握查询DSL着实不易。本文在前文的基础上进一步深入学习。
1. 精确检索 vs 全文检索
Elasticsearch中所有检索主要可分为三类:
- 精确检索
- 全文检索
- 两者组合检索(简称组合检索)
文档字段可分为两类:精确文本(keyword)和分析文本(text,也称为全文本)。精确文本如user_id, date, email_addresses等。分析文本如product_description 、 email_body等。通过这些字段名称可以理解,对应文本内容可以被分析(分词),通常是人类理解的自然语言。
查询文档可以通过精确值进行过滤检索。此时检索条件返回二值(是、否),例如,文档的user_id等于123,创建时间是否在一定日期范围内等。
另一方面,通过分析分别进行文档检索,基于相关性返回检索结果,不再是二值(是、否)。例如,文档的分析文本中包括Hello,Elasticsearch。那么通过该Hello world 或 Elasticsearch tutorial都可以检索到该文本。
从这个角度我们能推断全文检索是非常复杂的操作,依据不同类型文本数据涉及到不同分析包实现。如一些分析包实现是用于特定语言分析,缺省分析包是标准分析器,按照单词进行分词,转成小写并删除标点符号。因为全文检索比精确检索更加复杂,故性能上应该精确检索要更好。有时也称全文检索为分析检索。
2. Query DSL
elasticsearch 查询有一个或多个查询子句构成。查询子句能被组合创建其他查询子句,称为组合查询子句。所有查询子句有下面两者格式:
{
QUERY_CLAUSE: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
{
QUERY_CLAUSE: {
FIELD_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
}
语法规则:查询子句可以重复地嵌套在其他查找子句内。
{
QUERY_CLAUSE {
QUERY_CLAUSE: {
QUERY_CLAUSE: {
QUERY_CLAUSE: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
}
}
}
下面分别对一些主要的查询子句进行说明。
3. 常见查询子句
3.1. Match 查询子句
Match 查询子句是最通用、最常用的查询子句。其非常智能,当运行在分析文本字段时则执行全文检索查询,对精确值字段时则执行过滤查询。
下面示例,第一个查询子句在description
字段上执行全文检索,而其他两个字段则针对精确值执行过滤检索。
{ "match": { "description": "Fourier analysis signals processing" }}
{ "match": { "date": "2014-09-01" }}
{ "match": { "visible": true }}
3.2. Match All子句
Match All子句返回所有文档。类似于Sql:SELECT * FROM table
。
{ "match_all": {} }
3.3. Term/Terms 查询子句
Term/Terms子句各自用于使用单个值或多个值过滤精确值字段。在多值情况下,使用OR进行连接。
举例,第一个子句查询所有tag字段中包括“math”的文档。第二个查询所有文档的tag字段包括 “math” 或 “statistics”。
{ "term": { "tag": "math" }}
{ "terms": { "tag": ["math", "statistics"] }}
3.4. Multi Match子句
Multi Match子句在多个字段上执行匹配查询。
{
"multi_match": {
"query": "probability theory",
"fields": ["title", "body"]
}
}
3.5. Exists 和 Missing 子句
exists子句检查是否包括特定字段,missing子句检查文档在特定字段上没有值,类似于Sql 的is null 或 is not null 子句。示例如下:
{
"exists" : {
"field" : "title"
}
}
{
"missing" : {
"field" : "title"
}
}
3.6. Range 子句
Range 过滤子句用于过滤数值或日期字段在一定范围内,使用gt gte lt lte
四个操作。
{ "range" : { "age" : { "gt" : 30 } } }
{
"range": {
"born" : {
"gte": "01/01/2012",
"lte": "2013",
"format": "dd/MM/yyyy||yyyy"
}
}
}
3.7. Bool 子句
有其他查询子句构建查询子句称为组合查询子句。注意组合查询子句也可以组合其他组合查询子句,允许多层嵌套。
boo查询子句是组合查询子句的一个示例,常用于使用布尔操作组合多个查询子句。有三种支持的操作 must must_not 和 should,分别对应 AND , NOT , 和 OR 。
举例,加入有索引posts,需查询包括 math的且不包括 probability,同时也可以包括 unread 或 favorited。
{
"bool": {
"must": { "term": { "tag": "math" }},
"must_not": { "term": { "tag": "probability" }},
"should": [
{ "term": { "favorite": true }},
{ "term": { "unread": true }}
]
}
}
3.8. 使用过滤组合全文检索
前面已经分别讨论了精确查询上下文和全文检索上下文,但实际应用中通常需要组合两者。一般使用filter子句进行组合。
下面示例搜索posts索引中的文档,首先body字段中进行全文检索"Probability Theory",然后在增加条件upvotes 大于20 且 tag字段中包括 “frequentist” 关键字进行过滤。
{
"query": {
"bool": {
"must": [
{"match": { "body": "Probability Theory" }}
],
"filter": {
"bool": {
"must": {
"range": { "upvotes" : { "gt" : 20 } }
},
"must_not": { "term": { "tag": "frequentist" } }
}
}
}
}
}
4. 总结
elasticsearch 的查询DSL的核心思维是全局检索文档及过滤文档。本文分别介绍了不同类型的语法结构并通过示例进行说明,希望对你有帮助。
推荐阅读
-
6.Request Query 详解
-
Query类详解
-
详解Elasticsearch Query DSL
-
Oracle层级查询语句(hierarchical query)connect by 用法详解
-
PHP函数http_build_query使用详解_PHP
-
Elasticsearch Query DSL 整理总结(一)—— Query DSL 概要,MatchAllQuery,全文查询简述
-
Oracle层级查询语句(hierarchical query)connect by 用法详解
-
PHP函数http_build_query使用详解_PHP
-
PHP函数http_build_query使用详解
-
在JPA的@Query注解中使用limit条件(详解)