必须用elasticsearch/elasticsearch官方包(v8.x)连接ES 8.x,禁用自动建索引并为中文字段配置IK分词器,写入用bulk+指定ID,搜索用match_phrase并确保text类型与analyzer匹配。

用官方客户端建立稳定连接
PHP本身不带Elasticsearch支持,必须通过elasticsearch/elasticsearch官方包接入。直接手写curl或file_get_contents容易漏掉认证头、超时控制和429重试逻辑,还可能因Content-Type缺失返回406错误。
安装命令:
composer require elasticsearch/elasticsearch:^8.0
注意版本严格对齐:ES 8.x服务端只能配v8.x客户端,混用会报错。
初始化示例:
- hosts写成http://elasticsearch:9200(Docker环境)或http://192.168.1.100:9200(宿主机IP),别用localhost——PHP容器里它指向自己
- 启用Basic Auth时,host字符串中直接带凭证:https://user:pass@127.0.0.1:9200
- 开发可临时关SSL验证:->setSSLVerification(false);生产环境必须传入CA证书路径
- 检查cURL扩展是否启用:php -m | grep curl,没输出就去php.ini打开extension=curl
中文搜索前必须手动建索引+配分词器
不显式创建索引就调index(),ES 8.x默认拒绝自动建索引(action.auto_create_index: false)。更关键的是,text字段若不指定analyzer,会走standard分词器——对中文完全无效,“笔记本”搜不出来是常态。
正确做法是提前用indices()->create()定义mapping,例如:
- title字段设为'type' => 'text', 'analyzer' => 'ik_smart'
- 确保Elasticsearch已安装对应版本的IK插件(如ES 8.12.2 → elasticsearch-analysis-ik-8.12.2.zip)
- mapping里避免写_type字段,v7+已废弃,写了会报“Unknown key for a START_OBJECT”
写入数据要注意ID、批量与刷新策略
单条插入用index(),但务必传id参数。不传ID ES会自动生成UUID,后续更新或删除就失去可控性。
批量导入绝不能循环调index(),网络开销会爆炸。改用bulk(),body结构要按index + doc成对组织:
- 插入100条?一次bulk请求搞定,不是100次HTTP往返
- 刚写入就搜不到?默认refresh间隔1秒。测试时可加'refresh' => 'true'强制刷新(线上慎用)
- 高并发写入场景,建议用refresh_interval: -1暂停刷新,导入完再恢复
搜索要分清match、match_phrase与中文适配
match是分词后任意匹配,“北京天气”可能命中含“北京”和“天气”的两处不相邻句子;match_phrase要求分词结果顺序连续出现,更适合短语精确检索。
中文搜索生效的前提:
- 字段类型必须是text,且analyzer已设为ik_smart或jieba
- 查询body结构要规范,例如:
$params = [ 'index' => 'articles', 'body' => [ 'query' => [ 'match_phrase' => [ 'title' => '北京天气' ] ] ] ];
想兼顾相关性与精度,可用multi_match配合type: 'phrase_prefix'。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











