Elasticsearch DSL 核心语法大全:match、bool、range、聚合查询实战解析

发布于:2025-08-01 ⋅ 阅读:(19) ⋅ 点赞:(0)

DSL,全称为Domain Specific Language,即领域特定语言,是一种旨在特定领域内高效解决具体问题的编程或查询语言。与通用编程语言(如Java、Python等)相比,DSL专注于一个特定的应用领域,提供了针对该领域的更精确和高效的抽象。

在Elasticsearch中,DSL指的是Elasticsearch提供的基于JSON格式的完整查询语言,被称为Query DSL。这种语言使用户能够定义复杂的搜索查询,并支持多种类型的查询子句,包括但不限于全文搜索、结构化查询、聚合分析等。通过使用Query DSL,用户可以灵活地构建查询条件,控制结果排序,进行分页处理,甚至执行复杂的统计分析任务。例如,你可以使用它来执行简单的关键词匹配查询,也可以构建复杂的布尔查询来组合多个查询条件。这使得Elasticsearch不仅是一个强大的搜索引擎,也是一个灵活的数据分析工具。

一、准备测试数据

在深入学习 DSL 之前,我们需要先创建一个索引并填充一些测试数据。

1. 创建商品索引 (products)

PUT http://192.168.130.61:9200/products
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0
  },
  "mappings": {
    "properties": {
      "item": { "type": "keyword" },
      "title": { "type": "text" },
      "price": { "type": "float" },
      "group": { "type": "integer" },
      "brand": { "type": "keyword" },
      "hobby": { "type": "text" },
      "created_at": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" }
    }
  }
}

2. 批量写入测试数据

POST http://192.168.130.61:9200/_bulk
{ "index": { "_index": "products" } }
{ "item": "PROD-001", "title": "复古风格木质书桌", "price": 899.00, "group": 1, "brand": "家逸", "hobby": "阅读", "created_at": "2025-07-01 10:00:00" }
{ "index": { "_index": "products" } }
{ "item": "PROD-002", "title": "人体工学电脑椅", "price": 1299.50, "group": 1, "brand": "舒适达", "hobby": "办公", "created_at": "2025-07-02 11:30:00" }
{ "index": { "_index": "products" } }
{ "item": "PROD-003", "title": "智能恒温保温杯", "price": 158.00, "group": 2, "brand": "智饮", "hobby": "品茶", "created_at": "2025-07-03 14:20:00" }
{ "index": { "_index": "products" } }
{ "item": "PROD-004", "title": "无线蓝牙降噪耳机", "price": 699.00, "group": 2, "brand": "声悦", "hobby": "听音乐", "created_at": "2025-07-04 16:45:00" }
{ "index": { "_index": "products" } }
{ "item": "PROD-005", "title": "专业电竞游戏鼠标", "price": 299.99, "group": 3, "brand": "极光", "hobby": "游戏", "created_at": "2025-07-05 09:15:00" }
{ "index": { "_index": "products" } }
{ "item": "PROD-006", "title": "高清便携投影仪", "price": 2199.00, "group": 3, "brand": "视界", "hobby": "观影", "created_at": "2025-07-06 13:50:00" }
{ "index": { "_index": "products" } }
{ "item": "PROD-007", "title": "多功能厨房料理机", "price": 118.00, "group": 4, "brand": "厨乐", "hobby": "烹饪", "created_at": "2025-07-07 18:30:00" }
{ "index": { "_index": "products" } }
{ "item": "PROD-008", "title": "天然有机棉四件套", "price": 399.00, "group": 5, "brand": "安睡", "hobby": "睡眠", "created_at": "2025-07-08 20:10:00" }
{ "index": { "_index": "products" } }
{ "item": "PROD-009", "title": "户外折叠野营帐篷", "price": 599.00, "group": 6, "brand": "探路者", "hobby": "露营", "created_at": "2025-07-09 08:00:00" }
{ "index": { "_index": "products" } }
{ "item": "PROD-010", "title": "儿童益智积木玩具", "price": 89.90, "group": 7, "brand": "乐智", "created_at": "2025-07-10 15:25:00" }
{ "index": { "_index": "products" } }
{ "item": "PROD-011", "title": "静音加湿器", "price": 188.00, "group": 5, "brand": "润物", "created_at": "2025-07-11 12:00:00" }
{ "index": { "_index": "products" } }
{ "item": "PROD-012", "title": "复古金属台灯", "price": 256.00, "group": 1, "brand": "光影", "hobby": "阅读", "created_at": "2025-07-12 17:40:00" }

说明:所有数据均为虚构,不涉及任何真实用户或商业信息。


二、什么是 DSL?

Elasticsearch 提供了基于 JSON 的完整 Query DSL(Domain Specific Language,领域特定语言) 来定义查询。DSL 使得构建复杂查询变得灵活且强大。它分为两种主要类型:

  • 叶查询子句 (Leaf query clauses):针对特定字段搜索特定值,如 match, term, range
  • 复合查询子句 (Compound query clauses):组合多个查询子句,如 bool 查询。

三、核心 DSL 查询案例

3.1 全文检索 - match 查询

对文本字段进行分词搜索,找到包含任意一个分词的文档。

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "match": {
      "title": "书桌 椅子"
    }
  }
}

结果:会返回标题中包含“书桌”或“椅子”(或“椅子”相关分词)的文档,如 PROD-001PROD-002


3.2 完全匹配 - match_phrase 查询

要求查询词项必须作为一个整体短语出现,顺序和距离都需匹配。

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "match_phrase": {
      "title": "人体工学"
    }
  }
}

结果:只返回标题中精确包含“人体工学”这个短语的文档,如 PROD-002


3.3 全量查询 - match_all

返回索引中的所有文档。

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "match_all": {}
  }
}

提示:直接发送 GET http://192.168.130.61:9200/products/_search 不带请求体,默认行为等同于 match_all


3.4 分页查询 - sizefrom

控制返回结果的数量和起始位置。

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "match": {
      "group": 1
    }
  },
  "size": 3,
  "from": 0
}

参数说明

  • size: 每页显示条数,默认 10。
  • from: 跳过的文档数(偏移量),默认 0。
  • 计算公式:第 N 页的 from = (N-1) * size

温馨提示:避免深度分页(如 from 非常大),性能会急剧下降。生产环境建议使用 Search AfterScroll API。


3.5 指定返回字段 - _source

只返回 _source 中的指定字段,减少网络传输量。

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "match": {
      "group": 1
    }
  },
  "size": 5,
  "from": 0,
  "_source": ["item", "title", "price", "group"]
}

结果:返回的文档只包含 item, title, price, group 这四个字段。


3.6 查询存在字段的文档 - exists

查找包含指定字段(且字段值不为 null)的文档。

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "exists": {
      "field": "hobby"
    }
  }
}

结果:返回 hobby 字段有值的文档,如 PROD-001, PROD-002 等。


3.7 语法高亮 - highlight

在返回结果中对匹配的文本进行高亮标记。

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "match": {
      "title": "椅子"
    }
  },
  "highlight": {
    "pre_tags": ["<span style='color:red; font-weight:bold;'>"],
    "post_tags": ["</span>"],
    "fields": {
      "title": {}
    }
  }
}

结果:在 title 字段中,“椅子”一词会被包裹在红色加粗的 <span> 标签内。


3.8 基于字段排序 - sort

对查询结果按指定字段进行排序。

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "match": {
      "group": 1
    }
  },
  "sort": [
    {
      "price": {
        "order": "desc"
      }
    }
  ]
}

结果group 为 1 的商品按 price 降序排列(从高到低)。


3.9 多条件查询 - bool

组合多个查询条件,是构建复杂查询的核心。

9.1 must(必须满足)

所有 must 子句都必须匹配。

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match_phrase": {
            "title": "保温杯"
          }
        },
        {
          "term": {
            "price": 158
          }
        }
      ]
    }
  }
}

结果:返回标题包含“保温杯”价格等于 158 的文档,即 PROD-003

9.2 must_not(必须不满足)

所有 must_not 子句都不能匹配。

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "match": {
            "group": 7
          }
        },
        {
          "match_phrase": {
            "title": "儿童"
          }
        }
      ]
    }
  }
}

结果:返回 group 不是 7 标题不包含“儿童”的文档。

9.3 should(满足其一)

满足一个或多个 should 子句。可通过 minimum_should_match 控制最少匹配数量。

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "group": 3 } },
        { "match_phrase": { "title": "投影仪" } },
        { "match": { "price": 299.99 } }
      ],
      "minimum_should_match": 2
    }
  },
  "sort": [
    { "price": { "order": "desc" } }
  ]
}

结果:返回至少满足上述三个条件中两个的文档,并按价格降序排列。


3.10 精确匹配多个值 - terms

查找字段值在指定列表中的文档。

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "terms": {
      "price": [158, 118, 188]
    }
  }
}

结果:返回价格为 158、118 或 188 的文档,如 PROD-003, PROD-007, PROD-011


3.11 范围查询 - range

查找字段值在指定范围内的文档。

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "bool": {
      "must": [
        { "match_phrase": { "group": 5 } }
      ],
      "filter": {
        "range": {
          "price": {
            "gte": 300,
            "lte": 500
          }
        }
      }
    }
  }
}

结果:返回 group 为 5 价格在 300 到 500 之间的文档,即 PROD-008

参数说明

  • gt: 大于
  • lt: 小于
  • gte: 大于等于
  • lte: 小于等于

注意filter 子句不参与相关性评分计算,通常比 must 更高效。


3.12 多词搜索(operator

控制 match 查询中多个词项的逻辑关系。

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "match": {
      "title": {
        "query": "智能 保温",
        "operator": "and"
      }
    }
  },
  "highlight": {
    "pre_tags": ["<em>"],
    "post_tags": ["</em>"],
    "fields": {
      "title": {}
    }
  }
}

结果:只有当 title 同时包含“智能”和“保温”时才匹配,如 PROD-003。默认 operatoror


3.13 权重提升 - boost

为特定查询条件赋予更高的权重,影响文档的相关性得分。

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "group": 1 } }
      ],
      "should": [
        {
          "match_phrase": {
            "title": {
              "query": "书桌",
              "boost": 10
            }
          }
        },
        {
          "match_phrase": {
            "title": {
              "query": "椅子",
              "boost": 5
            }
          }
        }
      ]
    }
  },
  "highlight": {
    "fields": {
      "title": {}
    }
  }
}

结果:在 group 为 1 的商品中,包含“书桌”的文档得分会远高于仅包含“椅子”的文档,因此 PROD-001 会排在 PROD-002 前面。


四、聚合查询(Aggregations)

用于对数据进行统计分析,不返回原始文档。

4.1 统计每个组的商品数量

POST http://192.168.130.61:9200/products/_search
{
  "aggs": {
    "product_count_by_group": {
      "terms": {
        "field": "group"
      }
    }
  },
  "size": 0
}

结果:返回每个 group 值对应的商品数量统计。


4.2 查找 6 组商品中最贵的

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "match": {
      "group": 6
    }
  },
  "aggs": {
    "max_price_in_group_6": {
      "max": {
        "field": "price"
      }
    }
  },
  "size": 0
}

结果:返回 group 为 6 的商品中的最高价格。


4.3 查找 1 组商品中最便宜的

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "match": {
      "group": 1
    }
  },
  "aggs": {
    "min_price_in_group_1": {
      "min": {
        "field": "price"
      }
    }
  },
  "size": 0
}

结果:返回 group 为 1 的商品中的最低价格。


4.4 计算 5 组商品的平均价格

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "match": {
      "group": 5
    }
  },
  "aggs": {
    "avg_price_in_group_5": {
      "avg": {
        "field": "price"
      }
    }
  },
  "size": 0
}

结果:返回 group 为 5 的商品的平均价格。


4.5 计算购买 5 组所有商品的总价格

POST http://192.168.130.61:9200/products/_search
{
  "query": {
    "match": {
      "group": 5
    }
  },
  "aggs": {
    "total_cost_group_5": {
      "sum": {
        "field": "price"
      }
    }
  },
  "size": 0
}

结果:返回 group 为 5 的所有商品价格之和。


五、推荐阅读

  • 官方 Query DSL 文档: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html
  • 官方聚合文档: https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html

网站公告

今日签到

点亮在社区的每一天
去签到