4. 边界参数概念:搜索请求中的边界参数定义、分页、排序、过滤、高亮参数的作用域

在领域驱动设计的搜索索引聚合查询中,边界参数(Boundary Parameters)是连接用户查询意图与搜索引擎底层执行计划的关键契约。它们定义了“查什么、怎么查、返回什么、如何展示”的完整边界。本章将系统阐述分页、排序、过滤、高亮四大核心边界参数的定义、作用域及领域建模中的配置策略。

核心观点:边界参数不是简单的 HTTP 查询字符串,而是领域层对搜索交互协议的显式建模。每个参数都应具备明确的领域语义、作用域边界和默认值契约。

4.1 边界参数的定义与分类

边界参数从领域视角可分为三类:

分类 参数示例 作用域 领域语义
结果控制参数 page, size, sort 查询结果集 定义返回数据的数量、顺序和分段方式
条件约束参数 filter, range, term 查询条件域 缩小匹配范围,排除无关文档
展示增强参数 highlight, fields, source 响应展示层 控制返回字段、高亮片段等展示行为
领域建模提示:在聚合查询的边界参数配置中,建议将参数定义在独立的 SearchRequest 值对象中,而非散落在方法签名里。这有助于保持领域层的封装性和可测试性。

4.2 分页参数:深度与偏移的领域权衡

分页参数是最常见的边界参数,但其作用域往往被低估。典型的分页参数包括:

  • page:当前页码(从 0 或 1 开始)
  • size:每页文档数
  • from:偏移量(常用于深度分页)
  • search_after:游标分页(避免深度分页性能问题)

不同分页策略的作用域对比:

策略 适用场景 作用域限制 领域风险
偏移分页(from + size) 前几页查询,用户交互友好 深度分页时性能急剧下降 超过 10000 条后可能被搜索引擎拒绝
游标分页(search_after) 深度分页、实时数据流 只能向前翻页,不支持随机跳转 需要维护排序字段的唯一性
键集分页(keyset) 静态数据集、导出场景 依赖排序字段的稳定性 排序字段变更会导致数据遗漏
分页策略作用域对比图 偏移分页 作用域:前 10000 条 风险:深度分页 OOM 游标分页 作用域:全量数据 限制:仅向前翻页 键集分页 作用域:静态数据集 依赖:排序字段稳定 领域建模建议 1. 默认使用游标分页作为首选策略 2. 偏移分页仅用于前 5 页的用户交互场景 3. 在领域层显式声明分页策略的边界上限

4.3 排序参数:领域有序性的显式表达

排序参数定义了搜索结果的有序规则。在领域驱动设计中,排序不应仅仅是字段名+方向的组合,而应体现领域的有序性语义。

排序参数的核心要素:

  • 排序字段:必须是索引中已映射的字段,且通常为 keyword、numeric、date 类型
  • 排序方向:asc(升序)或 desc(降序)
  • 排序模式:min、max、avg(适用于多值字段)
  • 缺失值处理:_last、_first 或自定义默认值
常见陷阱:在聚合查询中,排序参数的作用域可能被错误地应用到聚合桶内而非文档级别。务必在领域层明确区分“文档排序”与“聚合桶排序”的边界。

排序参数在领域模型中的配置示例:

// 领域层排序值对象
public class SortCriteria {
    private String field;          // 排序字段(领域字段名)
    private SortDirection direction; // ASC / DESC
    private SortMode mode;         // MIN / MAX / AVG
    private MissingValue missing;  // _LAST / _FIRST / custom
    
    // 领域工厂方法
    public static SortCriteria byRelevance() {
        return new SortCriteria("_score", SortDirection.DESC);
    }
    
    public static SortCriteria byDateDesc(String field) {
        return new SortCriteria(field, SortDirection.DESC);
    }
}

4.4 过滤参数:查询与过滤的领域边界

过滤参数(Filter)与查询参数(Query)在搜索引擎中有本质区别。过滤参数的作用域是精确匹配,不参与相关性评分,且结果可被缓存。

维度 查询参数(Query) 过滤参数(Filter)
作用域 影响相关性评分 仅做布尔匹配
缓存 不缓存 可缓存结果集
性能 相对较慢 更快,适合频繁执行
领域语义 用户意图匹配 业务规则约束
典型场景 全文搜索、模糊匹配 状态过滤、范围限定

过滤参数在聚合查询中的典型作用域:

  • 全局过滤:应用于整个搜索请求,影响所有聚合桶
  • 聚合级过滤:仅影响特定聚合桶的计算
  • 后过滤:在查询和聚合计算完成后,对结果集做二次过滤

4.5 高亮参数:展示层的领域边界

高亮参数控制搜索结果中匹配片段的展示方式。虽然高亮是展示层行为,但其配置参数需要在领域层进行建模,以确保不同搜索场景的一致性。

高亮参数的核心配置项:

参数 作用域 说明
pre_tags / post_tags 片段包裹 高亮前后缀标签,如 <em>
fragment_size 片段长度 每个高亮片段的字符数
number_of_fragments 片段数量 每个字段返回的最大片段数
fields 字段作用域 指定哪些字段需要高亮
type 高亮算法 unified、plain、fvh
领域建模实践:将高亮参数封装为 HighlightConfig 值对象,并在领域层提供不同场景的工厂方法(如 forTitle()、forContent()),避免展示层直接拼接高亮参数。

4.6 边界参数的作用域层级模型

所有边界参数在搜索请求中形成层级作用域模型。理解这个模型是正确配置聚合查询的前提。

边界参数作用域层级模型 搜索请求(SearchRequest) 全局边界参数:分页、排序、全局过滤、高亮默认值 查询参数(Query) 过滤参数(Filter) 聚合参数(Aggregation):聚合级过滤、子聚合边界 展示参数(Highlight / Source / Fields)

作用域层级的关键规则:

  1. 上层参数可被下层覆盖:全局分页参数可被聚合级的分页参数覆盖
  2. 过滤参数具有传递性:全局过滤条件自动传递到所有聚合桶
  3. 高亮参数作用域最小:仅影响最终返回的文档片段,不参与聚合计算
  4. 排序参数不可传递:文档排序与聚合桶排序是独立的边界
领域驱动设计原则:边界参数的作用域模型应在领域层通过值对象和工厂方法显式定义,而非在基础设施层通过 Map 或 JSON 对象隐式传递。这确保了参数变更时,领域逻辑的完整性不受破坏。