Elasticsearch是基于Lucene构建的分布式搜索引擎,通过倒排索引实现毫秒级全文检索。与关系数据库的LIKE模糊查询不同,Elasticsearch对文本进行分词、词项化和倒排索引,支持复杂的全文检索、相关性排序和聚合分析。在电商搜索、日志分析和企业知识库等场景中,Elasticsearch是最广泛部署的搜索引擎。
倒排索引构建与分词流程解析
Elasticsearch的全文检索基于倒排索引(Inverted Index)实现。文档写入时经过分析器(Analyzer)处理,流程如下:
– 字符过滤(Character Filter):处理HTML标签剥离、正则替换等,如html_strip过滤器的输入为<p>Hello</p>,输出为Hello
– 分词(Tokenizer):将文本切分为词项(Term),如standard分词器将”AI模型部署”切分为[AI, 模型, 部署]
– 词项过滤(Token Filter):对词项进行小写化、停用词移除、同义词扩展、词干提取等处理
– 倒排索引写入:将词项与文档ID列表的映射关系持久化到Lucene段文件
中文分词是Elasticsearch搜索质量的关键环节。默认的standard分词器对中文按单字切分,无法正确处理”人工智能”这类多字词语。IK Analysis插件是中文分词的主流方案:
# 安装IK分词器(版本需匹配ES版本)
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v8.12.0/elasticsearch-analysis-ik-8.12.0.zip
# 重启Elasticsearch
systemctl restart elasticsearch
# 验证分词效果
POST /_analyze
{
"analyzer": "ik_smart",
"text": "大模型推理优化与部署方案"
}
# ik_smart分词结果:[大模型, 推理, 优化, 与, 部署, 方案]
# ik_max_word分词结果:[大模型, 大型, 模型, 推理, 优化, 与, 部署, 方案]
ik_smart是粗粒度分词,适合搜索场景;ik_max_word是细粒度分词,适合索引阶段,两种模式配合使用可兼顾召回率和精确率。
索引映射与分析器自定义配置
创建索引时需显式定义字段映射和分析器配置。以下为电商商品搜索索引的完整映射配置:
PUT /products
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"analysis": {
"filter": {
"pinyin_filter": {
"type": "pinyin",
"keep_first_letter": true,
"keep_full_pinyin": true,
"keep_original": true,
"lowercase": true
},
"synonym_filter": {
"type": "synonym",
"synonyms": [
"手机,智能手机,移动电话",
"笔记本,笔记本电脑,laptop",
"耳机,耳麦,headset"
]
},
"length_filter": {
"type": "length",
"min": 2,
"max": 50
}
},
"analyzer": {
"ik_search_analyzer": {
"type": "custom",
"tokenizer": "ik_max_word",
"filter": ["lowercase", "synonym_filter", "length_filter"]
},
"pinyin_analyzer": {
"type": "custom",
"tokenizer": "ik_smart",
"filter": ["pinyin_filter", "lowercase"]
}
}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_search_analyzer",
"fields": {
"pinyin": {
"type": "text",
"analyzer": "pinyin_analyzer"
},
"keyword": {
"type": "keyword",
"ignore_above": 200
}
}
},
"description": {
"type": "text",
"analyzer": "ik_max_word"
},
"brand": {
"type": "keyword"
},
"category_id": {
"type": "integer"
},
"price": {
"type": "scaled_float",
"scaling_factor": 100
},
"sales_count": {
"type": "integer"
},
"status": {
"type": "keyword"
},
"created_at": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
}
}
}
}
关键配置说明:索引阶段使用ik_max_word细粒度分词提升召回率,搜索阶段使用ik_search_analyzer粗粒度分词提升精确率。同义词过滤器在搜索阶段生效,用户搜索”手机”能匹配到标题包含”智能手机”的文档。拼音字段支持拼音搜索,用户输入”shouji”也能匹配到”手机”。
相关性评分调优:BM25与Function Score
Elasticsearch默认使用BM25算法计算文档相关性评分。BM25公式综合考虑词项频率(TF)、逆文档频率(IDF)和文档长度归一化:
score = IDF * (TF * (k1 + 1)) / (TF + k1 * (1 - b + b * |d| / avgdl))
# IDF = log(1 + (N - n + 0.5) / (n + 0.5))
# N: 文档总数, n: 包含该词项的文档数
# TF: 词项在文档中出现的频率
# |d|: 当前文档长度, avgdl: 平均文档长度
# k1: 词频饱和参数(默认1.2),控制TF增长的影响衰减
# b: 长度归一化参数(默认0.75),控制文档长度归一化强度
调优BM25参数可以改善特定场景的搜索质量。短文本字段(如商品标题)适合较低的b值(0.3-0.5),长文本字段(如商品描述)适合较高的b值(0.75-1.0):
PUT /products/_settings
{
"index": {
"similarity": {
"title_bm25": {
"type": "BM25",
"k1": 1.2,
"b": 0.4
},
"description_bm25": {
"type": "BM25",
"k1": 1.5,
"b": 0.8
}
}
}
}
# 在映射中指定自定义相似度
PUT /products/_mapping
{
"properties": {
"title": {
"type": "text",
"similarity": "title_bm25",
"analyzer": "ik_max_word"
},
"description": {
"type": "text",
"similarity": "description_bm25",
"analyzer": "ik_max_word"
}
}
}
业务排序需求(如销量加权、新品优先、距离排序)通过Function Score查询实现:
POST /products/_search
{
"query": {
"function_score": {
"query": {
"bool": {
"must": [
{ "match": { "title": "无线耳机" } }
],
"filter": [
{ "term": { "status": "active" } }
]
}
},
"functions": [
{
// 销量越高分数越高,log1p平滑处理避免大销量值主导
"field_value_factor": {
"field": "sales_count",
"modifier": "log1p",
"factor": 0.5
}
},
{
// 近7天创建的商品加分
"filter": {
"range": { "created_at": { "gte": "now-7d" } }
},
"weight": 1.5
},
{
// 品牌权重,优先品牌商品
"filter": { "term": { "brand": "Apple" } },
"weight": 2.0
},
{
// 距离衰减(有位置信息时)
"gauss": {
"location": {
"origin": "31.23,121.47",
"scale": "10km",
"decay": 0.5
}
}
}
],
"score_mode": "sum",
"boost_mode": "multiply",
"min_score": 0.1
}
},
"size": 20,
"sort": [ "_score" ]
}
多字段检索与Bool查询组合策略
实际搜索场景中,用户输入的查询词需要匹配多个字段,不同字段设置不同的权重。通过Bool查询的should子句和multi_match实现:
POST /products/_search
{
"query": {
"bool": {
"must": [
{ "term": { "status": "active" } }
],
"should": [
{
// 标题完全匹配权重最高
"multi_match": {
"query": "蓝牙耳机降噪",
"type": "best_fields",
"fields": ["title^3", "description^1"],
"tie_breaker": 0.3,
"minimum_should_match": "75%"
}
},
{
// 品牌匹配
"match": { "brand": "蓝牙耳机降噪" }
},
{
// 拼音搜索
"match": { "title.pinyin": "蓝牙耳机降噪" }
}
],
"minimum_should_match": 1
}
},
"highlight": {
"fields": {
"title": {
"pre_tags": ["<em>"],
"post_tags": ["</em>"],
"number_of_fragments": 2,
"fragment_size": 100
}
}
},
"aggs": {
"categories": {
"terms": { "field": "category_id", "size": 10 }
},
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{ "to": 100 },
{ "from": 100, "to": 500 },
{ "from": 500, "to": 2000 },
{ "from": 2000 }
]
}
}
}
}
minimum_should_match设为”75%”表示查询词至少75%的词项需要匹配文档,防止关键词分散匹配导致不相关结果排名靠前。tie_breaker设为0.3表示最佳字段得分占70%,其他字段得分占30%。
搜索性能优化与索引策略
搜索延迟受索引数据量、查询复杂度和硬件资源三方面影响。生产环境的关键优化措施:
– 索引分片规划:单分片建议10-50GB,分片数等于数据节点数或其整数倍。3节点集群建议3个主分片1个副本分片,总分片数6个,每节点承载2个分片。
– 过滤器缓存:Bool查询的filter子句结果会被缓存,将高频过滤条件放在filter中而非must中:
// filter子句不参与评分,结果缓存,性能更优
{
"bool": {
"must": [
{ "match": { "title": "耳机" } }
],
"filter": [
{ "term": { "status": "active" } },
{ "range": { "price": { "gte": 100, "lte": 5000 } } },
{ "terms": { "category_id": [1, 2, 3] } }
]
}
}
– 索引预排序:index_sort按排序字段预排序索引段文件,查询时可以提前终止扫描:
PUT /products
{
"settings": {
"index": {
"sort.field": ["sales_count", "created_at"],
"sort.order": ["desc", "desc"]
}
}
}
– 搜索请求缓存:对聚合查询结果启用request cache,重复查询直接返回缓存结果。query字符串中包含now等时间函数的查询不缓存。
POST /products/_search?request_cache=true
{
"size": 0,
"aggs": {
"category_stats": {
"terms": { "field": "category_id", "size": 10 },
"aggs": {
"avg_price": { "avg": { "field": "price" } }
}
}
}
}
– 慢查询监控:配置slowlog阈值,超过阈值的查询写入日志,用于定位和分析性能问题:
PUT /products/_settings
{
"index.search.slowlog.threshold.query.warn": "2s",
"index.search.slowlog.threshold.query.info": "500ms",
"index.search.slowlog.threshold.fetch.warn": "1s"
}
索引数据量超过1亿条时,建议启用数据温热分层(hot-warm-cold architecture),热数据存SSD节点,冷数据存HDD节点,通过ILM策略自动迁移。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/elasticsearch-quan-wen-jian-suo-shi-zhan-fen-ci-qi-pei-zhi/