使用DSL语言搜索数据
当用户需要与Elasticsearch集群进行交互以执行复杂的全文检索或数据分析时,DSL (Domain Specific Language) 作为Elasticsearch的原生查询语言,基于JSON格式构建,能够精确表达查询意图,是客户端与Elasticsearch集群交互的最佳语言。
什么是DSL?
DSL是Elasticsearch定义的一套基于JSON的请求体格式。它主要包含两个上下文:
- Query Context(查询上下文):回答“这个文档与查询子句匹配程度如何?”的问题。会计算“_score”(相关性评分),用于结果排序。例如:match。
- Filter Context(过滤上下文):回答“这个文档是否匹配?”的问题(Yes/No)。不计算评分,且结果会被Elasticsearch自动缓存,性能更高。例如:term、range。
DSL查询通常在Kibana的Dev Tools中执行,请求体和返回信息都是JSON格式。
本文列举了常用DSL查询语句,全量的DSL查询语句请参见Query DSL。
基础查询:匹配所有
使用“match_all”查询以获取索引中的所有文档,相当于SQL语言中的“SELECT * FROM table”。适用于需要检索所有记录的场景。
例如,执行如下命令,在“test”索引中匹配所有文档。
1 2 3 4 5 6 | GET /test/_search { "query": { "match_all": {} } } |
复合查询:多条件组合
使用“bool (must, filter)”查询结构以实现多条件组合查询,相当于SQL语言中的“where”。适用于需要根据多个条件筛选文档的场景。
例如,执行如下命令,查询所有状态为“published”且发布日期在“2015-01-01”之后(过滤条件),同时标题或内容中包含“Search”(搜索条件)的文档。
GET /_search
{
"query": {
"bool": {
"must": [
{
"match": {
"title": "Search"
}
},
{
"match": {
"content": "search"
}
}
],
"filter": [
{
"term": {
"status": "published"
}
},
{
"range": {
"publish_date": {
"gte": "2015-01-01"
}
}
}
]
}
}
} 其中,“must”和“filter”字段的区别:
- must:用于指定必须匹配的条件,且这些条件会影响文档的相关度评分。文档越匹配,分越高,排越前。
- filter:用于指定必须匹配的条件,但这些条件不会影响文档的相关度评分。性能优于must,适合用于过滤结构化数据。
对于不需要计算相关度分数的条件(如状态、时间范围、类别),建议放入“filter”中以提升性能。
聚合分析
使用“aggs (terms)”查询结构以实现分组聚合查询,相当于SQL语言中的“Group by”。适用于需要对文档进行分组统计的场景。
例如,执行如下命令,统计“test”索引中,不同标题(title)出现的次数。
GET /test/_search
{
"aggs": {
"titles": {
"terms": {
"field": "title.keyword"
}
}
}
} 使用title.keyword的原因:
- text类型用于全文检索(分词)。例如Hello World会被拆解为hello和world。直接对“text”字段聚合会报错(Fielddata is disabled),因为它极其消耗内存。
- keyword类型用于精确匹配和聚合。它保存的是Hello World这个完整字符串。
集群默认会为字符串创建多字段(Multi-field),即“title”用于搜索,“title.keyword”用于聚合。