面试题答案
一键面试索引结构设计
- 字段类型选择
- 对于商品名称、描述等文本字段,使用
text
类型,并配置合适的分词器,如ik_max_word
用于中文分词,以确保搜索时能够准确匹配。例如:
{ "mappings": { "properties": { "product_name": { "type": "text", "analyzer": "ik_max_word" } } } }
- 对于数值类型的销量、价格等字段,使用
long
(销量)、float
或double
(价格)类型,以便进行数值计算和排序。例如:
{ "mappings": { "properties": { "sales": { "type": "long" }, "price": { "type": "float" } } } }
- 对于商品名称、描述等文本字段,使用
- 多字段存储
- 对于需要精确匹配和全文搜索的字段,创建多字段。例如,对于商品名称,除了
text
类型的字段用于全文搜索,还可以创建一个keyword
类型的字段用于精确匹配。
{ "mappings": { "properties": { "product_name": { "type": "text", "analyzer": "ik_max_word", "fields": { "keyword": { "type": "keyword" } } } } } }
- 对于需要精确匹配和全文搜索的字段,创建多字段。例如,对于商品名称,除了
查询语句编写
- 基本查询
- 使用
bool
查询来组合多个条件。例如,要搜索名称中包含 “手机” 且价格在 1000 到 5000 之间的商品:
{ "query": { "bool": { "must": [ { "match": { "product_name": "手机" } }, { "range": { "price": { "gte": 1000, "lte": 5000 } } } ] } } }
- 使用
- 相关性评分
- ElasticSearch 默认使用 BM25 算法进行相关性评分。可以通过调整
match
查询中的boost
参数来增加特定字段的相关性权重。例如,提高商品描述字段对相关性的影响:
{ "query": { "bool": { "must": [ { "match": { "product_description": { "query": "手机", "boost": 2 } } } ] } } }
- ElasticSearch 默认使用 BM25 算法进行相关性评分。可以通过调整
- 综合排序
- 使用
sort
数组来指定多个排序因素及其顺序。例如,先按相关性评分降序,再按销量降序,最后按价格升序:
{ "query": { "match": { "product_name": "手机" } }, "sort": [ "_score", { "sales": { "order": "desc" } }, { "price": { "order": "asc" } } ] }
- 使用
权重调整
- 相关性权重
- 如上述查询语句中,通过
boost
参数调整不同字段在相关性评分中的权重。可以根据业务经验和 A/B 测试来确定合适的权重值。例如,如果商品名称的匹配比描述更重要,可以将商品名称的boost
值设为 3,描述的boost
值设为 1。
- 如上述查询语句中,通过
- 多因素权重整合
- 可以通过自定义脚本评分来更灵活地整合多个排序因素的权重。例如,假设相关性评分、销量和价格的权重分别为 0.5、0.3 和 0.2,可以编写如下脚本:
{ "query": { "function_score": { "query": { "match": { "product_name": "手机" } }, "functions": [ { "filter": { "match_all": {} }, "script_score": { "script": { "source": "0.5 * _score + 0.3 * doc['sales'].value / max_sales + 0.2 * 10000 / doc['price'].value", "params": { "max_sales": 10000 // 假设的最大销量值,需根据实际情况调整 } } } } ], "score_mode": "sum", "boost_mode": "replace" } } }
优化措施
- 索引优化
- 定期进行索引的合并和优化操作,如
optimize
(在 ElasticSearch 7.0 之前)或forcemerge
,减少段的数量,提高查询性能。 - 根据数据量和查询模式,合理设置索引的分片数和副本数。例如,如果数据量较大且读操作频繁,可以适当增加副本数;如果查询主要集中在部分数据上,可以调整分片数以提高查询局部性。
- 定期进行索引的合并和优化操作,如
- 缓存机制
- 利用 ElasticSearch 的缓存,如请求缓存(
request_cache
),对于相同的查询可以直接从缓存中获取结果,减少查询执行时间。可以在请求中设置request_cache: true
开启缓存。 - 对于热门商品的搜索结果,可以在应用层设置缓存,如使用 Redis 缓存搜索结果,减少对 ElasticSearch 的请求压力。
- 利用 ElasticSearch 的缓存,如请求缓存(
- 性能监控与调优
- 使用 ElasticSearch 的监控工具,如 Kibana 的监控面板,实时监控索引的性能指标,如查询响应时间、索引写入速度等。根据监控数据,调整索引结构、查询语句和服务器资源配置,以优化搜索性能。