DSL查询与过滤
1、 什么是DSL查询
由ES提供丰富且灵活的查询语言叫做DSL查询(Query DSL),它允许你构建更加复杂、强大的查询。
DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现。
DSL查询是ES提供的通用查询方式,这种方式最大的特点是开发语言的无关性,即任意的客户端只要支持HTTP请求,就可以通过JSON格式的查询数据完成复杂的搜索。
对于简单查询,使用查询字符串比较好,但是对于复杂查询,由于条件多,逻辑嵌套复杂,查询字符串不易组织与表达,且容易出错,因此推荐复杂查询通过DSL使用JSON内容格式的请求体代替。
DSL有两个部分组成:DSL查询,DSL过滤。
DSL过滤语句和DSL查询语句非常相似,但是它们的使用目的却不同:
DSL过滤(精确查找)查询文档的方式更像是对于我的条件“有”或者“没有”,而DSL查询(模糊查询)则像是“有多像”。
DSL过滤和DSL查询在性能上的区别:
过滤结果可以缓存并应用到后续请求。
查询语句同时匹配文档,计算相关性,所以更耗时,且不缓存。
过滤语句可有效地配合查询语句完成文档过滤。
原则上,使用DSL查询做全文本搜索或其他需要进行相关性评分的场景,其它全用DSL过滤。
2、 DSL查询
使用DSL查询,必须要传递query参数给ES。
GET _search
{"query": YOUR_QUERY_HERE}
一个常用的相对完整的DSL查询:
GET itsource/employee/_search { "query": { "match": {"sex":"女"} }, "_source": ["id","name"], "from": 20, "size": 10, "sort": [{"join_date": "desc"},{"age": "asc"}] }
select id,name from t_user where name like “%heh%” order by id desc limit 0,10.
上面的DSL查询语句代表:查询公司员工性别为女的员工,并按照加入时间降序、年龄升序排列,最终返回第21条至30条数据(只返回名字、年龄和email字段)
3、DSL过滤
模糊查询用DSL的查询语句,精确查询用DSL过滤语句。
2.0以上的用法
{ "query": { "bool": { "must": [ {"match": {"description": "search" }} ], "filter": { "term": {"age": "12"} } } }, "_source": ["id","name"], "from": 20, "size": 10, "sort": [{"join_date": "desc"},{"age": "asc"}] }
4、使用DSL查询与过滤
① 全匹配(match_all)
普通搜索(匹配所有文档):
{ "query" : { "match_all" : {} } }
如果需要使用过滤条件(在所有文档中过滤,红色部分默认可不写):
{ "query" : { "bool" : { "must" : [{ "match_all":{} }], "filter":{....} } } }
② 标准查询(match和multi_match)
match查询是一个标准查询,不管你需要全文本查询还是精确查询基本上都要用到它。
如果你使用match查询一个全文本字段,它会在真正查询之前用分析器先分析查询字符:
{ "query": { "match": { "fullName": "Steven King" } } }
上面的搜索会对Steven King分词,并找到包含Steven或King的文档,然后给出排序分值。
如果用 match 下指定了一个确切值,在遇到数字,日期,布尔值或者 not_analyzed的字符串时,它将为你搜索你给定的值,如:
{ "match": { "age": 20 }}
{ "match": { "date": "2016-05-01" }}
{ "match": { "public": true }}
{ "match": { "tag": "full_text" }}
multi_match 查询允许你做 match查询的基础上同时搜索多个字段:
{ "query":{ "multi_match": { "query": "Steven King", "fields": [ "fullName","title" ] } } }
上面的搜索同时在fullName和title字段中匹配。
提示:match一般只用于全文字段的匹配与查询,一般不用于过滤。
③单词搜索与过滤(Term和Terms)
{ "query": { "bool": { "must": { "match_all": {} }, "filter": { "term": { "age": "20" } } } } }
Terms搜索与过滤
{ "query": { "terms": { "tags": ["jvm", "hadoop", "lucene"], "minimum_match": 2 } } }
minimum_match:至少匹配个数,默认为1
④ 组合条件搜索与过滤(Bool)
组合搜索bool可以组合多个查询条件为一个查询对象,查询条件包括must、should和must_not。
例如:查询爱好有吃米饭,同时也有喜欢游戏或运动,且出生于1990-06-30及之后的人。Range:范围
{ "query": { "bool": { "must": [{"term": {"hobby": "吃米饭"}}], "should": [{"term": {"hobby": "游戏"}}, {"term": {"hobby": "运动"}} ], "must_not": [ {"range" :{"birth_date":{"lt": "1990-06-30"}}} ], "filter": [...], "minimum_should_match": 1 } } }
提示: 如果 bool 查询下没有must子句,那至少应该有一个should子句。但是 如果有 must子句,那么没有 should子句也可以进行查询。
⑤ 范围查询与过滤(range)
range过滤允许我们按照指定范围查找一批数据:
{ "query":{ "range": { "age": { "gte": 20, "lt": 30 } } } }
上例中查询年龄大于等于20并且小于30。
gt:> gte:>= lt:< lte:<=
⑥ 存在和缺失过滤器(exists和missing)
{ "query": { "bool": { "must": [{ "match_all": {} }], "filter": { "exists": { "field": "gps" } } } } }
提示:exists和missing只能用于过滤结果。
⑦ 前匹配搜索与过滤(prefix)
和term查询相似,前匹配搜索不是精确匹配,而是类似于SQL中的like ‘key%’
{ "query": { "prefix": { "fullName": "黄" } } }
上例即查询姓黄的所有人。
⑧ 通配符搜索(wildcard)
使用*代表0~N个,使用?代表1个。
{ "query": { "wildcard": { "fullName": "文*华" } } }