**核心原则:Elasticsearch是否会分词取决于使用的查询类型和字段映射配置**。这与传统数据库完全不同,是理解ES搜索行为的关键。
## 一、会分词的查询类型
### 1. `match` 查询(最常用)
```json
{
"query": {
"match": {
"content": "中文分词测试"
}
}
}
```
- **会分词**:使用字段映射中定义的`search_analyzer`(或默认`analyzer`)
- 中文示例:`"content": "苹果手机"` 可能被分成 `["苹果", "手机"]`
- 默认使用`OR`操作符,匹配任一分词即可
- 可设置`"operator": "AND"`要求匹配所有分词
### 2. `match_phrase` 查询
```json
{
"query": {
"match_phrase": {
"content": " Elasticsearch教程 "
}
}
}
```
- **会分词**,但要求分词后的词语保持原始顺序
- 保留词语间的位置信息,适合短语精确匹配
- 示例:`"quick brown fox"` 会分词为 `["quick", "brown", "fox"]` 并要求按此顺序出现
### 3. `query_string` / `simple_query_string`
```json
{
"query": {
"query_string": {
"query": "Java AND Python",
"fields": ["title", "content"]
}
}
}
```
- **会分词**,且支持类似SQL的查询语法
- 默认使用`standard`分析器分词
- 注意:特殊字符需要转义,可能导致意外行为(新手慎用)
## 二、不会分词的查询类型
### 1. `term` / `terms` 查询(最常用)
```json
{
"query": {
"term": {
"status": "published"
}
}
}
```
- **不分词**:将搜索条件视为完整精确值
- 适用于:关键字字段(`.keyword`)、ID、状态码等不需要分词的字段
- **重要陷阱**:对text类型字段直接使用term查询通常得不到结果!
### 2. `range` / `exists` 等结构化查询
- 日期范围、数值范围等查询不会进行文本分词
- 基于字段的原始值进行比较
## 三、关键机制解析
### 1. 字段映射决定分词行为
```json
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word", // 索引时分词器
"search_analyzer": "ik_smart" // 搜索时分词器
},
"title.keyword": {
"type": "keyword"
}
}
}
}
```
- **text类型字段**:存储时被分词,搜索时根据查询类型决定是否再次分词
- **keyword类型字段**:始终不分词,用于精确匹配、聚合、排序
- **最佳实践**:对需要同时支持全文搜索和精确匹配的字段,使用多字段(multi-field)设计
### 2. 分词过程可视化
使用`_analyze` API查看实际分词效果:
```json
GET /_analyze
{
"analyzer": "ik_max_word",
"text": "中华人民共和国国歌"
}
```
返回结果:
```json
{
"tokens": [
{"token": "中华人民共和国", "position": 0},
{"token": "中华人民", "position": 1},
{"token": "中华", "position": 2},
{"token": "华人", "position": 3},
...
]
}
```
## 四、常见误区与解决方案
### 误区1:对text字段使用term查询
```json
// 错误示例(通常返回空结果):
{
"query": {
"term": {
"title": "Elasticsearch 入门教程"
}
}
}
```
**正确做法**:
- 全文搜索用`match`:`"match": { "title": "Elasticsearch 入门教程" }`
- 精确匹配用`.keyword`:`"term": { "title.keyword": "完整标题文本" }`
### 误区2:忽略大小写问题
- 默认`standard`分析器会转为小写:`"Apple" → "apple"`
- 中文分词器通常保留原始大小写,需注意大小写敏感性
### 误区3:未配置中文分词器
- 默认英文分词器对中文按单字切分:`"中文测试" → ["中","文","测","试"]`
- **解决方案**:安装IK、jieba等中文分词插件
## 五、最佳实践建议
1. **明确字段用途**:
- 全文搜索 → `text` + 合适的分词器
- 精确值/聚合 → `keyword`
- 邮箱/URL等 → 使用`normalizer`进行大小写标准化
2. **查询类型选择原则**:
- 用户输入的自然语言 → `match` 或 `multi_match`
- 精确值过滤(状态、类型)→ `term`
- 标签/分类等多值匹配 → `terms`
3. **生产环境必备**:
```json
// 标准字段设计示例
"product_name": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
```
4. **调试技巧**:
- 使用`"explain": true`查看评分细节
- 用`_validate` API检查查询是否被正确解析
- 通过Kibana的"Dev Tools"实时测试分词效果
> **关键总结**:Elasticsearch不是"输入什么搜什么"的简单系统。理解**索引时分析**和**查询时分析**的双重过程,是掌握ES搜索行为的核心。永远先检查字段mapping,再选择合适的查询类型。