diff --git a/api/result_formatter.py b/api/result_formatter.py index 7770cf2..f3fd9f7 100644 --- a/api/result_formatter.py +++ b/api/result_formatter.py @@ -308,10 +308,20 @@ class ResultFormatter: for value_bucket in value_counts['buckets']: # Check if this spec value is selected is_selected = (name, value_bucket['key']) in selected_specs + + # 使用 reverse_nested 的 product_count 统计产品数量(而不是规格条目数量) + # 如果没有 product_count(兼容旧格式),回退到 doc_count + product_count_agg = value_bucket.get('product_count', {}) + if product_count_agg and 'doc_count' in product_count_agg: + count = product_count_agg['doc_count'] + else: + # 回退到 doc_count(兼容旧格式,但这不是我们想要的计数方式) + count = value_bucket.get('doc_count', 0) + value = FacetValue( value=value_bucket['key'], label=str(value_bucket['key']), - count=value_bucket['doc_count'], + count=count, selected=is_selected ) values.append(value) diff --git a/search/es_query_builder.py b/search/es_query_builder.py index dbe44fa..7b6bd77 100644 --- a/search/es_query_builder.py +++ b/search/es_query_builder.py @@ -829,13 +829,16 @@ class ESQueryBuilder: def build_facets( self, - facet_configs: Optional[List['FacetConfig']] = None + facet_configs: Optional[List['FacetConfig']] = None, + use_reverse_nested: bool = True ) -> Dict[str, Any]: """ 构建分面聚合。 Args: facet_configs: 分面配置对象列表 + use_reverse_nested: 是否使用 reverse_nested 统计产品数量(默认 True) + 如果为 False,将统计嵌套文档数量(性能更好但计数可能不准确) 支持的字段类型: - 普通字段: 如 "category1_name"(terms 或 range 类型) @@ -844,6 +847,10 @@ class ESQueryBuilder: Returns: ES aggregations 字典 + + 性能说明: + - use_reverse_nested=True: 统计产品数量,准确性高但性能略差(通常影响 < 20%) + - use_reverse_nested=False: 统计嵌套文档数量,性能更好但计数可能不准确 """ if not facet_configs: return {} @@ -884,19 +891,31 @@ class ESQueryBuilder: if field.startswith("specifications."): name = field[len("specifications."):] agg_name = f"specifications_{name}_facet" + # 使用 reverse_nested 统计产品(父文档)数量,而不是规格条目(嵌套文档)数量 + # 这样可以确保分面计数反映实际的产品数量,与搜索结果数量一致 + base_value_counts = { + "terms": { + "field": "specifications.value", + "size": size, + "order": {"_count": "desc"} + } + } + + # 如果启用 reverse_nested,添加子聚合统计产品数量 + if use_reverse_nested: + base_value_counts["aggs"] = { + "product_count": { + "reverse_nested": {} + } + } + aggs[agg_name] = { "nested": {"path": "specifications"}, "aggs": { "filter_by_name": { "filter": {"term": {"specifications.name": name}}, "aggs": { - "value_counts": { - "terms": { - "field": "specifications.value", - "size": size, - "order": {"_count": "desc"} - } - } + "value_counts": base_value_counts } } } diff --git a/third-party/clip-as-service b/third-party/clip-as-service new file mode 160000 index 0000000..0341057 --- /dev/null +++ b/third-party/clip-as-service @@ -0,0 +1 @@ +Subproject commit 03410570d4398084f5ca5c88ad968248e0f3fc5d -- libgit2 0.21.2