搜索建议与自动补全:Completion Suggester

FreeGuideOnline 最新 2026-07-03

json PUT /products { "mappings": { "properties": { "product_name": { "type": "text", "analyzer": "standard" }, "suggest": { "type": "completion", "analyzer": "simple" } } } }


- `suggest` 字段的 `type` 必须为 `completion`。
- `analyzer` 指定在索引输入文本时使用的分词器。默认是 `simple` 分析器(将输入转为小写并按非字母字符分隔)。如需支持中文、拼音等,可将分析器更改为 `ik_max_word` 或自定义拼音分析器。

**建议**:通常会为建议功能单独创建一个字段,与全文检索字段分开,以便对分析流程独立控制。

### 步骤二:索引文档

索引时,我们需要向 `suggest` 字段提供 `input`(和可选的 `weight`、`output`)。文档结构如下:

```json
POST /products/_doc/1
{
  "product_name": "iPhone 13 Pro Max",
  "suggest": {
    "input": [ "iPhone 13", "iPhone 13 Pro", "iPhone 13 Pro Max" ],
    "weight": 100
  }
}

此处我们提供了多个 input 变体,即使用户只输入“iPhone 13”,也能匹配到该文档。weight 为 100,可根据商品热度、销量等动态设定。

你也可以使用更简洁的语法,直接将 suggest 设置为一个字符串或数组,此时 weight 不可控,但系统会自动创建 inputoutput 均为该值、权重为 1 的条目。

批量索引示例:

POST /products/_bulk
{"index":{"_id":1}}
{"product_name":"iPhone 13","suggest":{"input":["iPhone 13","iphone","apple phone"],"weight":200}}
{"index":{"_id":2}}
{"product_name":"iPhone 13 Pro","suggest":{"input":["iPhone 13 Pro","iphone pro"],"weight":180}}
{"index":{"_id":3}}
{"product_name":"Samsung Galaxy S22","suggest":{"input":["Samsung Galaxy S22","s22","galaxy"],"weight":150}}

步骤三:发送建议请求

使用 _search 端点的 suggest 块发起 Completion 请求,而不需要 query。基本格式:

POST /products/_search
{
  "suggest": {
    "product-suggest": {
      "prefix": "iph",
      "completion": {
        "field": "suggest",
        "size": 5,
        "skip_duplicates": true,
        "fuzzy": {
          "fuzziness": "AUTO"
        }
      }
    }
  }
}

参数解析:

  • prefix:用户已输入的字符串。Completion 会查找所有以此前缀开头的 input
  • field:指定 completion 类型的字段名。
  • size:返回的最大建议数,默认 5。
  • skip_duplicates:是否对拥有相同 text 的建议去重(默认 false,但建议开启避免列表重复)。
  • fuzzy:开启模糊匹配,处理拼写错误。fuzziness 可设为 AUTO(根据输入长度自动计算编辑距离)、12。对于中文补全,需谨慎开启模糊,以免错误匹配过多。

返回结果示例结构:

{
  "suggest": {
    "product-suggest": [
      {
        "text": "iph",
        "offset": 0,
        "length": 3,
        "options": [
          {
            "text": "iPhone 13",
            "_index": "products",
            "_id": "1",
            "_score": 200.0,
            "_source": { ... }
          },
          {
            "text": "iPhone 13 Pro",
            "_index": "products",
            "_id": "2",
            "_score": 180.0,
            "_source": { ... }
          }
        ]
      }
    ]
  }
}

_score 的值即为权重,降序排列。你可以从 _source 中提取需要展示的字段(如价格、图片等),但注意:若仅需文本列表,可以设置 "_source": false 减少网络传输。

进阶配置与优化

1. 支持上下文过滤

Completion Suggester 支持 Context Suggester,允许根据条件(如商品分类、用户所在地域)过滤建议。这需要定义 contexts 映射:

"suggest": {
  "type": "completion",
  "contexts": [
    {
      "name": "category",
      "type": "category"
    }
  ]
}

索引时指定 context:

"suggest": {
  "input": ["iPhone 13"],
  "weight": 200,
  "contexts": {
    "category": ["electronics", "phones"]
  }
}

查询时传入上下文:

"completion": {
  "field": "suggest",
  "size": 5,
  "contexts": {
    "category": ["phones"]
  }
}