TP5.1对接Elasticsearch需封装单例Client、区分term/match查询、正确处理.keyword后缀、校验分页防deep paging、显式指定高亮字段、严格匹配字段类型与查询方式。

TP5.1 对接 Elasticsearch 不能只靠 ClientBuilder::create()->build() 一把梭——不封装连接、不区分 termQuery 和 matchQuery、不处理 .keyword 后缀,搜出来的结果大概率错漏百出,分页和高亮也容易崩。
为什么直接 new Client 会出 Connection refused?
TP5.1 是短生命周期 PHP 请求模型,每次 new 一个 Elasticsearch\Client 就新建 HTTP 连接,没复用、没超时控制、没重试策略。并发稍高就触发 socket 耗尽,报 Connection refused 或 cURL error 7: Failed to connect。
- 必须封装成单例服务类,用
think\Container绑定或静态属性缓存 client 实例 - 连接配置里要设
setRetries(2),避免瞬时网络抖动失败 - host 列表建议写成
['192.168.1.10:9200', '192.168.1.11:9200'],别只写 localhost —— 容器环境 DNS 解析可能失败
多条件组合搜索怎么写?BoolQueryBuilder 是核心
ES 原生 DSL 复杂难维护,TP5.1 里推荐用 elasticsearch/elasticsearch 客户端 + 手动拼数组,而不是强套 Spring Data 风格的 QueryBuilders(Java 的那一套在 PHP 里没对应实现)。
-
must对应 AND:比如['must' => [['match' => ['name' => $kw]], ['range' => ['price' => ['gte' => $min, 'lte' => $max]]]]] -
should需配"minimum_should_match": 1,否则空数组也命中 - 精确匹配品牌/状态等枚举值,必须用
term查brand.keyword字段,写成['term' => ['brand.keyword' => '华为']],不能用match - 多个 should 并列且只要满足其一,外层要套一层
bool,再放进主must或should,否则逻辑错乱
分页和高亮怎么不丢数据?from/size 有坑
ES 默认 from + size ≤ 10000,TP5.1 里如果用户翻到第 500 页(from=4990),直接报 query_phase_execution_exception 错误。
- 分页参数必须校验:
max_page = min($page, 1000),硬限制防止 deep paging - 高亮字段要显式指定
fields,否则默认只高亮content,而你查的是title和desc会没效果 - 返回结果里
highlight是可选字段,得先判isset($hit['_source']['highlight'])再取值,不然 Notice 报错 - 总数要用
$response['hits']['total']['value'],注意 ES 7.x 后total是对象不是数字
最常被忽略的是字段类型和查询方式的严格对应:text 字段用 match,keyword 字段用 term,数值字段用 range —— 混用会导致无结果或全量命中。映射定义和查询语句必须对齐,这点没法靠调试发现,得看索引 mapping 输出确认。


















