Laravel本身不提供开箱即用的Elasticsearch全文关键词检索封装,必须手动对接官方elasticsearch/elasticsearch客户端并自定义Scout引擎,或选用维护活跃的社区驱动;字段映射、DSL构造、分词适配任一缺失均导致search()静默返回空数组。

直接上结论:Laravel 本身不提供开箱即用的 Elasticsearch 全文关键词检索封装,必须手动对接官方 elasticsearch/elasticsearch 客户端 + 自定义 Scout 引擎,或选用维护活跃的社区驱动(如 laravel/scout-elastic),但后者对 ES 8.x 支持仍需补丁。别信“装完就能搜”的说法——字段映射、DSL 构造、分词适配这三步漏一个,search() 就返回空数组且无报错。
为什么 Scout::search('xxx') 没结果但也不报错
这是最常踩的坑:Scout 调用 search() 方法后静默失败,实际是底层 DSL 写错了,ES 返回了 200 状态但 hits 为空。常见原因包括:
- 没重写
ElasticsearchEngine::search(),直接用了父类空实现 - 用
match查询英文字段却没设"analyzer": "english",中文字段没装 IK 插件或没指定"analyzer": "ik_smart" - 字段名在
toSearchableArray()里拼错了,比如写成'title_zh',但 ES mapping 里是title - ES 8.x 默认禁用
type,但旧引擎代码还硬塞_doc到 URL 路径,导致 404 或忽略查询
如何让关键词检索真正“全文”起来(不是模糊匹配)
默认 match 是自然语言模式,对短词、标点、大小写敏感度低;要精准命中关键词,得手动构造 DSL 并控制分析器。关键点:
- 用
match_phrase替代match,避免词序打散(例如搜"Laravel Scout"不会匹配到 “Scout is Laravel”) - 中文必须显式指定 analyzer:
"analyzer": "ik_smart"(IK 分词)或"analyzer": "standard"(单字切分) - 字段需在 ES mapping 中提前定义为
"index": true,且不能是"index": false或"enabled": false - 示例 DSL 片段(用于重写
search()):{"query":{"match_phrase":{"title":{"query":"Laravel","analyzer":"standard"}}
Laravel 10+ + ES 8.x 连接配置最容易错的三处
ES 8 强制 HTTPS、Basic Auth、证书校验,本地开发不调通就卡死。配置时盯紧这三点:
-
hosts数组里必须带协议和端口,写成['https://localhost:9200'],不能只写['localhost:9200'](会走 HTTP,被拒绝) - 禁用证书验证仅限开发:
'ssl' => ['verify_peer' => false, 'verify_peer_name' => false],否则 cURL 报错cURL error 60 - 认证必须用
basic_authentication键传数组:['username' => 'elastic', 'password' => 'changeme'],别往 headers 里手动塞Authorization字符串
真正难的不是写几行代码,而是每次改一个参数都得 curl 测一次 mapping、看一眼 ES 日志、再比对 PHP 的请求体——DSL 写错、字段类型不匹配、分词器没生效,这三者混在一起时,search() 返回空就是唯一提示。


















