Elasticsearch是基于Lucene构建的分布式全文搜索引擎,在日志分析、电商搜索、文档检索等NoSQL选型应用场景中广泛使用。相比关系型数据库的LIKE模糊查询,Elasticsearch通过倒排索引实现毫秒级全文检索,支持复杂的全文搜索、聚合分析和地理位置查询。本文演示Elasticsearch索引设计、中文分词器配置和查询优化的完整流程。
Elasticsearch倒排索引与分词机制
Elasticsearch的全文搜索基于倒排索引(Inverted Index)。传统数据库的B+树索引是从文档找到关键词,倒排索引反向操作——从关键词找到包含它的文档。写入文档时,Elasticsearch对文本字段执行分词(Analysis),将文本拆分为词项(Term),建立词项到文档ID的映射关系。
分词过程由Analyzer完成,包含三个阶段:Character Filter(字符过滤,如去除HTML标签)、Tokenizer(分词,将文本拆分为词项)、Token Filter(词项过滤,如转小写、去停用词、同义词扩展)。Elasticsearch内置多种Analyzer,标准分词器standard适用于英文,但对中文只能按单字切分,无法识别中文词语边界。
索引Mapping设计与字段类型选择
Mapping定义索引的字段结构和分词规则。设计一个电商商品索引:
PUT /products
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"analysis": {
"analyzer": {
"ik_smart_analyzer": {
"type": "custom",
"tokenizer": "ik_smart",
"filter": ["lowercase", "asciifolding"]
},
"ik_max_word_analyzer": {
"type": "custom",
"tokenizer": "ik_max_word",
"filter": ["lowercase", "asciifolding"]
},
"pinyin_analyzer": {
"type": "custom",
"tokenizer": "ik_smart",
"filter": ["pinyin_filter", "lowercase"]
}
},
"filter": {
"pinyin_filter": {
"type": "pinyin",
"keep_first_letter": true,
"keep_full_pinyin": true,
"keep_original": true,
"lowercase": true
}
}
}
},
"mappings": {
"properties": {
"product_id": {
"type": "keyword"
},
"title": {
"type": "text",
"analyzer": "ik_max_word_analyzer",
"search_analyzer": "ik_smart_analyzer",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"pinyin": {
"type": "text",
"analyzer": "pinyin_analyzer"
}
}
},
"description": {
"type": "text",
"analyzer": "ik_max_word_analyzer",
"search_analyzer": "ik_smart_analyzer"
},
"category": {
"type": "keyword"
},
"tags": {
"type": "keyword"
},
"price": {
"type": "double"
},
"sales_count": {
"type": "integer"
},
"status": {
"type": "keyword"
},
"created_at": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||epoch_millis"
},
"location": {
"type": "geo_point"
},
"suggest": {
"type": "completion",
"analyzer": "ik_smart_analyzer"
}
}
}
}
Mapping设计的关键决策点:
索引时分词器与搜索时分词器:title字段使用ik_max_word_analyzer(索引时最大粒度切分,提高召回率),search_analyzer使用ik_smart_analyzer(搜索时智能切分,提高精确度)。这种”索引时细粒度、搜索时粗粒度”的策略是中文搜索的最佳实践。
text与keyword多字段:title.fields.keyword定义了子字段,用于精确匹配和排序。text类型用于全文检索,keyword类型用于精确匹配、聚合和排序。
拼音搜索:title.fields.pinyin子字段配置拼音分词器,支持用户输入”shouji”搜索到”手机”。
IK中文分词器安装与词典扩展
IK Analysis Plugin是Elasticsearch最常用的中文分词插件,提供ik_smart(智能切分)和ik_max_word(最大粒度切分)两种模式。安装方式:
# 在Elasticsearch安装目录执行
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v8.12.0/elasticsearch-analysis-ik-8.12.0.zip
# 安装后重启所有节点
systemctl restart elasticsearch
IK分词器内置词典,但业务场景通常需要自定义词典。配置自定义词典:
# 编辑IK插件配置
vim config/analysis-ik/IKAnalyzer.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<entry key="ext_dict">custom_dict.dic</entry>
<entry key="ext_stopwords">custom_stop.dic</entry>
<entry key="remote_ext_dict">http://yunthe.com/dict/updated.dic</entry>
</properties>
# 自定义词典文件 custom_dict.dic
# 每行一个词
云计算
大数据
人工智能
前端开发
后端开发
微服务架构
# 停用词词典 custom_stop.dic
的
了
在
是
和
remote_ext_dict支持远程词典热更新——Elasticsearch定期请求该URL获取最新词典,返回的Last-Modified或ETag变化时自动重新加载,无需重启节点。
验证分词效果:
POST /products/_analyze
{
"analyzer": "ik_max_word_analyzer",
"text": "人工智能与大数据融合发展"
}
# 返回词项:
# ["人工智能", "智能", "与", "大数据", "数据", "融合", "发展"]
POST /products/_analyze
{
"analyzer": "ik_smart_analyzer",
"text": "人工智能与大数据融合发展"
}
# 返回词项:
# ["人工智能", "与", "大数据", "融合", "发展"]
Query DSL查询语法与相关性优化
Elasticsearch使用Query DSL(JSON格式)定义查询。常用的全文搜索查询:
POST /products/_search
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "人工智能开发",
"fields": ["title^3", "description^1", "tags^2"],
"type": "best_fields",
"operator": "or",
"minimum_should_match": "75%",
"tie_breaker": 0.3
}
}
],
"filter": [
{ "term": { "status": "published" } },
{ "range": { "price": { "gte": 0, "lte": 9999 } } }
],
"should": [
{ "term": { "category": "人工智能" } }
]
}
},
"sort": [
{ "_score": { "order": "desc" } },
{ "sales_count": { "order": "desc" } }
],
"from": 0,
"size": 20,
"highlight": {
"fields": {
"title": {
"pre_tags": ["<em>"],
"post_tags": ["</em>"],
"number_of_fragments": 0
}
}
}
}
查询结构解析:bool.must中的multi_match在title、description、tags三个字段搜索,title权重最高(^3)。filter中的条件不参与相关性评分但影响过滤,性能优于must。should提升匹配category为”人工智能”的文档得分。sort先按相关性得分排序,再按销量排序。highlight对title字段高亮匹配关键词。
相关性优化技巧:使用function_score自定义得分权重,将销量、评分、上架时间等业务因素纳入相关性计算:
POST /products/_search
{
"query": {
"function_score": {
"query": {
"multi_match": {
"query": "人工智能",
"fields": ["title^3", "description"]
}
},
"functions": [
{
"field_value_factor": {
"field": "sales_count",
"factor": 0.1,
"modifier": "log1p",
"missing": 0
}
},
{
"exp": {
"created_at": {
"origin": "now",
"scale": "30d",
"decay": 0.5
}
}
}
],
"score_mode": "multiply",
"boost_mode": "sum"
}
}
}
该查询将文本相关性得分与销量因子(log1p平滑处理)、时间衰减因子(30天半衰期)相乘叠加,使高销量、新上架且文本匹配的商品排在前面。
Elasticsearch全文搜索的效果高度依赖分词器配置和Mapping设计。中文场景中IK分词器的词典维护是持续优化的重点,业务新词、专有名词需要及时录入词典。索引分片数量根据数据量和节点数规划,通常每个分片控制在30-50GB以内以保证查询性能。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/elasticsearch-quan-wen-sou-suo-yin-qing-suo-yin-she-ji-yu/