<返回目录     Powered by claude/xia兄

第4课: 查询DSL

什么是Query DSL?

Query DSL(Domain Specific Language)是Elasticsearch提供的基于JSON的查询语言,用于构建复杂的搜索查询。它分为两大类:叶子查询(Leaf Query)和复合查询(Compound Query)。

查询上下文 vs 过滤上下文

特性 查询上下文(Query Context) 过滤上下文(Filter Context)
作用 计算相关性评分 判断是否匹配(是/否)
性能 较慢,需要计算_score 更快,可以缓存
使用场景 全文搜索、相关性排序 精确匹配、范围过滤
示例 搜索"手机"相关商品 价格在1000-5000之间

全文查询(Full Text Queries)

1. Match查询

最常用的全文搜索查询,会对查询文本进行分词。

# 基础match查询
GET /products/_search
{
  "query": {
    "match": {
      "name": "苹果手机"
    }
  }
}

# 指定操作符(默认OR)
GET /products/_search
{
  "query": {
    "match": {
      "name": {
        "query": "苹果手机",
        "operator": "and"  # 必须同时包含"苹果"和"手机"
      }
    }
  }
}

# 设置最小匹配度
GET /products/_search
{
  "query": {
    "match": {
      "description": {
        "query": "轻薄 便携 高性能 长续航",
        "minimum_should_match": "75%"  # 至少匹配3个词
      }
    }
  }
}

2. Match Phrase查询

短语匹配,要求词条顺序一致。

# 精确短语匹配
GET /products/_search
{
  "query": {
    "match_phrase": {
      "description": "iPhone 15 Pro"
    }
  }
}

# 允许词条间有间隔(slop)
GET /products/_search
{
  "query": {
    "match_phrase": {
      "description": {
        "query": "iPhone Pro",
        "slop": 2  # 允许中间有最多2个词
      }
    }
  }
}

3. Multi Match查询

在多个字段上执行match查询。

# 多字段搜索
GET /products/_search
{
  "query": {
    "multi_match": {
      "query": "iPhone",
      "fields": ["name", "description", "brand"]
    }
  }
}

# 字段权重提升
GET /products/_search
{
  "query": {
    "multi_match": {
      "query": "手机",
      "fields": ["name^3", "description", "category^2"],
      "type": "best_fields"
    }
  }
}

# 不同的匹配类型
GET /products/_search
{
  "query": {
    "multi_match": {
      "query": "苹果手机",
      "fields": ["name", "description"],
      "type": "cross_fields",  # 跨字段匹配
      "operator": "and"
    }
  }
}

精确查询(Term-Level Queries)

1. Term查询

精确匹配,不分词,用于keyword、数字、日期等字段。

# 精确匹配品牌
GET /products/_search
{
  "query": {
    "term": {
      "brand.keyword": "Apple"
    }
  }
}

# 精确匹配价格
GET /products/_search
{
  "query": {
    "term": {
      "price": 7999
    }
  }
}

# 带权重的term查询
GET /products/_search
{
  "query": {
    "term": {
      "category.keyword": {
        "value": "手机",
        "boost": 2.0
      }
    }
  }
}

2. Terms查询

匹配多个精确值(OR关系)。

# 匹配多个品牌
GET /products/_search
{
  "query": {
    "terms": {
      "brand.keyword": ["Apple", "Samsung", "Huawei"]
    }
  }
}

# 匹配多个价格
GET /products/_search
{
  "query": {
    "terms": {
      "price": [5999, 7999, 9999]
    }
  }
}

3. Range查询

范围查询,用于数字、日期等字段。

# 价格范围查询
GET /products/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 5000,  # 大于等于
        "lte": 10000  # 小于等于
      }
    }
  }
}

# 日期范围查询
GET /products/_search
{
  "query": {
    "range": {
      "release_date": {
        "gte": "2023-01-01",
        "lt": "2024-01-01",
        "format": "yyyy-MM-dd"
      }
    }
  }
}

# 相对时间查询
GET /logs/_search
{
  "query": {
    "range": {
      "timestamp": {
        "gte": "now-7d/d",  # 最近7天
        "lt": "now/d"
      }
    }
  }
}

4. Exists查询

查询字段存在的文档。

# 查询有description字段的文档
GET /products/_search
{
  "query": {
    "exists": {
      "field": "description"
    }
  }
}

# 查询没有description字段的文档
GET /products/_search
{
  "query": {
    "bool": {
      "must_not": {
        "exists": {
          "field": "description"
        }
      }
    }
  }
}

复合查询(Compound Queries)

Bool查询

Bool查询是最重要的复合查询,可以组合多个查询条件。

子句 说明 影响评分
must 必须匹配,相当于AND
should 应该匹配,相当于OR
must_not 必须不匹配,相当于NOT 否(过滤上下文)
filter 必须匹配,但不计算评分 否(过滤上下文)
# 复杂bool查询示例
GET /products/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "手机"
          }
        }
      ],
      "filter": [
        {
          "range": {
            "price": {
              "gte": 3000,
              "lte": 8000
            }
          }
        },
        {
          "term": {
            "status.keyword": "在售"
          }
        }
      ],
      "should": [
        {
          "term": {
            "brand.keyword": "Apple"
          }
        },
        {
          "term": {
            "brand.keyword": "Samsung"
          }
        }
      ],
      "must_not": [
        {
          "term": {
            "category.keyword": "二手"
          }
        }
      ],
      "minimum_should_match": 1
    }
  }
}

# 嵌套bool查询
GET /products/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "category": "手机"
          }
        }
      ],
      "filter": [
        {
          "bool": {
            "should": [
              {
                "range": {
                  "price": {
                    "lte": 3000
                  }
                }
              },
              {
                "term": {
                  "brand.keyword": "Apple"
                }
              }
            ]
          }
        }
      ]
    }
  }
}

其他常用查询

1. Wildcard查询(通配符)

# 通配符查询
GET /products/_search
{
  "query": {
    "wildcard": {
      "name.keyword": {
        "value": "iPhone*"  # *匹配任意字符,?匹配单个字符
      }
    }
  }
}

2. Prefix查询(前缀)

# 前缀查询
GET /products/_search
{
  "query": {
    "prefix": {
      "name.keyword": "iPhone"
    }
  }
}

3. Fuzzy查询(模糊)

# 模糊查询(容错搜索)
GET /products/_search
{
  "query": {
    "fuzzy": {
      "name": {
        "value": "iPone",  # 拼写错误
        "fuzziness": "AUTO"  # 自动计算编辑距离
      }
    }
  }
}
查询优化建议:

练习题

1. Match查询练习

2. Term查询练习

3. Bool查询练习

4. Multi Match练习

5. 高级查询

6. 实战场景

7. 性能对比

8. 调试查询

常见问题

Q: match和term有什么区别?

A: match用于全文搜索,会对查询文本分词;term用于精确匹配,不分词。match适用于text字段,term适用于keyword、数字、日期等字段。

Q: 什么时候用must,什么时候用filter?

A: 需要相关性评分时用must,只需要过滤数据时用filter。filter性能更好且可以缓存,建议优先使用。

Q: minimum_should_match如何使用?

A: 可以使用数字(至少匹配N个条件)、百分比(至少匹配N%的条件)或组合表达式。例如:"2"表示至少匹配2个,"75%"表示至少匹配75%。

Q: 如何提高查询性能?

A: 1) 使用filter代替must;2) 避免wildcard和regex查询;3) 合理设置分片数量;4) 使用routing减少查询分片;5) 启用查询缓存。