# Summary # Cues # Notes 执行链路 1. HTTP 请求入口 - api_server.py:29-67 @app.route("/search", methods=["GET"]) def search_routes(): query = request.args.get("q", "") # 获取查询参数 "兰州路线" size = int(request.args.get("size", 10)) results = search_engine.search(query, size) # 调用搜索引擎 2. 搜索引擎主函数 - route_search.py:171-183 def search(self, query: str, size: int = 10) -> List[Dict]: search_body = self.build_search_query(query) # 构建查询 response = self.es.search(index=self.index_name, body=search_body, size=size) 3. 构建搜索查询 - route_search.py:102-169 def build_search_query(self, query: str) -> Dict: # 3.1 提取目的地信息 destination_name, destination_code = self.extract_destination_from_query(query) # 返回: ("兰州", "620100") 4. 目的地提取 - route_search.py:95-100 def extract_destination_from_query(self, query: str) -> tuple: for city_name, city_code in self.config.city_codes.items(): if city_name in query: # "兰州" in "兰州路线" return city_name, city_code return None, None 5. 构建多字段查询 - route_search.py:106-128 # 对每个字段构建查询 for field, weight in self.config.field_weights.items(): # 字段权重配置 # 'destinations.abstract': 3.0 # 'destinations.city.name': 2.5 # 'route_name': 2.0 #.. 6. 添加专注度加分 - route_search.py:146-167 if destination_code: # 识别到"兰州",添加专注度加分 # 6.1 专注度字段加分 search_body["query"]["function_score"]["functions"].append({ "field_value_factor": { "field": f"focus_scores.620100", # 兰州的专注度分数 "factor": 2.0, "modifier": "sqrt" } }) # 6.2 短途路线加分 search_body["query"]["function_score"]["functions"].append({ "exp": { "metrics.duration_days": { "origin": 2, # 2天是理想值 "scale": 3, # 衰减范围 "decay": 0.5 } } }) 7. 专注度预计算 - route_search.py:48-71 def calculate_focus_score(self, route: Dict, target_city_code: str) -> float: # 计算POI占比 lanzhou_pois = sum(1 for poi in route['destinations']['poi'] if poi.get('city_code') == '620100') poi_ratio = lanzhou_pois / total_pois # 计算天数占比 lanzhou_days = sum(1 for day in route['itinerary'] if day.get('overnight_city_code') == '620100') day_ratio = lanzhou_days / total_days return poi_ratio * 0.6 + day_ratio * 0.4 8. 发送到 Elasticsearch 最终构建的查询体会发送到 ES,大致结构如下: { "query": { "function_score": { "query": { "bool": { "should":[ {"match": {"destinations.abstract": {"query": "兰州路线", "boost": 3.0}}}, {"nested": {"path": "destinations.city", "query": {"match": {"destinations.city.name": {"query": "兰州路线", "boost": 2.5}}}}}, {"match": {"route_name": {"query": "兰州路线", "boost": 2.0}}} //... 其他字段 ] } }, "functions":[ { "field_value_factor": { "field": "focus_scores.620100", "factor": 2.0, "modifier": "sqrt" } }, { "exp": { "metrics.duration_days": { "origin": 2, "scale": 3, "decay": 0.5 } } } ] } } } 评分计算示例 兰州城市经典2日游: - BM25 基础分:~10分(路线名、抽象目的地、城市都匹配) - 专注度加分:sqrt(1.0) * 2.0 = 2.0 - 短途加分:exp(0) * 1.5 = 1.5(2天正好是期望值) - 最终得分:10 * (1 + 2.0 + 1.5) = 15.81 甘青大环线: - BM25 基础分:~2分(仅城市字段部分匹配) - 专注度加分:sqrt(0.19) * 2.0 = 0.87 - 短途减分:exp(-2.33) * 1.5 = 0.15(10天远离期望值) - 最终得分:2 * (1 + 0.87 + 0.15) = 2.44