MST

星途 面试题库

面试题:ElasticSearch 如何在复杂业务场景下优化近实时搜索结果排序

假设存在一个电商平台的复杂业务场景,需要对商品进行近实时搜索并按相关性、销量、价格等多个因素综合排序。请详细描述你在 ElasticSearch 中会采取哪些策略和技术手段来实现并优化这种排序,包括但不限于索引结构设计、查询语句编写、权重调整等方面。
47.7万 热度难度
数据库ElasticSearch

知识考点

AI 面试

面试题答案

一键面试

索引结构设计

  1. 字段类型选择
    • 对于商品名称、描述等文本字段,使用 text 类型,并配置合适的分词器,如 ik_max_word 用于中文分词,以确保搜索时能够准确匹配。例如:
    {
        "mappings": {
            "properties": {
                "product_name": {
                    "type": "text",
                    "analyzer": "ik_max_word"
                }
            }
        }
    }
    
    • 对于数值类型的销量、价格等字段,使用 long(销量)、floatdouble(价格)类型,以便进行数值计算和排序。例如:
    {
        "mappings": {
            "properties": {
                "sales": {
                    "type": "long"
                },
                "price": {
                    "type": "float"
                }
            }
        }
    }
    
  2. 多字段存储
    • 对于需要精确匹配和全文搜索的字段,创建多字段。例如,对于商品名称,除了 text 类型的字段用于全文搜索,还可以创建一个 keyword 类型的字段用于精确匹配。
    {
        "mappings": {
            "properties": {
                "product_name": {
                    "type": "text",
                    "analyzer": "ik_max_word",
                    "fields": {
                        "keyword": {
                            "type": "keyword"
                        }
                    }
                }
            }
        }
    }
    

查询语句编写

  1. 基本查询
    • 使用 bool 查询来组合多个条件。例如,要搜索名称中包含 “手机” 且价格在 1000 到 5000 之间的商品:
    {
        "query": {
            "bool": {
                "must": [
                    {
                        "match": {
                            "product_name": "手机"
                        }
                    },
                    {
                        "range": {
                            "price": {
                                "gte": 1000,
                                "lte": 5000
                            }
                        }
                    }
                ]
            }
        }
    }
    
  2. 相关性评分
    • ElasticSearch 默认使用 BM25 算法进行相关性评分。可以通过调整 match 查询中的 boost 参数来增加特定字段的相关性权重。例如,提高商品描述字段对相关性的影响:
    {
        "query": {
            "bool": {
                "must": [
                    {
                        "match": {
                            "product_description": {
                                "query": "手机",
                                "boost": 2
                            }
                        }
                    }
                ]
            }
        }
    }
    
  3. 综合排序
    • 使用 sort 数组来指定多个排序因素及其顺序。例如,先按相关性评分降序,再按销量降序,最后按价格升序:
    {
        "query": {
            "match": {
                "product_name": "手机"
            }
        },
        "sort": [
            "_score",
            {
                "sales": {
                    "order": "desc"
                }
            },
            {
                "price": {
                    "order": "asc"
                }
            }
        ]
    }
    

权重调整

  1. 相关性权重
    • 如上述查询语句中,通过 boost 参数调整不同字段在相关性评分中的权重。可以根据业务经验和 A/B 测试来确定合适的权重值。例如,如果商品名称的匹配比描述更重要,可以将商品名称的 boost 值设为 3,描述的 boost 值设为 1。
  2. 多因素权重整合
    • 可以通过自定义脚本评分来更灵活地整合多个排序因素的权重。例如,假设相关性评分、销量和价格的权重分别为 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"
            }
        }
    }
    

优化措施

  1. 索引优化
    • 定期进行索引的合并和优化操作,如 optimize(在 ElasticSearch 7.0 之前)或 forcemerge,减少段的数量,提高查询性能。
    • 根据数据量和查询模式,合理设置索引的分片数和副本数。例如,如果数据量较大且读操作频繁,可以适当增加副本数;如果查询主要集中在部分数据上,可以调整分片数以提高查询局部性。
  2. 缓存机制
    • 利用 ElasticSearch 的缓存,如请求缓存(request_cache),对于相同的查询可以直接从缓存中获取结果,减少查询执行时间。可以在请求中设置 request_cache: true 开启缓存。
    • 对于热门商品的搜索结果,可以在应用层设置缓存,如使用 Redis 缓存搜索结果,减少对 ElasticSearch 的请求压力。
  3. 性能监控与调优
    • 使用 ElasticSearch 的监控工具,如 Kibana 的监控面板,实时监控索引的性能指标,如查询响应时间、索引写入速度等。根据监控数据,调整索引结构、查询语句和服务器资源配置,以优化搜索性能。