在 yii2.0.55 中启用 elasticsearch 全文搜索需完成四步:配置 elasticsearch 组件(键名必须为 elasticsearch)、定义带中文分词器(如 ik_max_word)的 mapping、创建索引并写入数据后调用 refresh()、最后通过 query() 或 rawquery() 执行检索。

在 Yii2.0.55 项目中启用 Elasticsearch 全文搜索功能,需完成客户端连接、索引映射定义、文档写入与基础检索逻辑四步闭环,缺一不可;若跳过 mapping 显式声明或忽略 analyzer 配置,中文字段将无法被分词,导致搜索完全失效。
配置 Elasticsearch 连接
打开 config/web.php 或 config/main.php,在 components 数组中添加 elasticsearch 组件:
【必须使用 elasticsearch 键名】 Yii2 的 ActiveRecord 默认只识别该键名,否则后续调用 Elasticsearch::getDb() 会抛出未定义连接异常。
添加如下配置:
'elasticsearch' => [<br> 'class' => 'yii\elasticsearch\Connection',<br> 'nodes' => [<br> ['http_address' => '127.0.0.1:9200'],<br> ],<br>],
确保 Elasticsearch 服务已在本地 9200 端口运行,且未被防火墙拦截;若使用远程节点,请替换 http_address 并确认跨域策略已放开。
定义 Elasticsearch 模型类
创建 common/models/ArticleSearch.php(路径可自定),继承 yii\elasticsearch\ActiveRecord:
类内必须重写 getDb() 方法,返回全局 elasticsearch 组件实例:
public static function getDb() {<br> return \Yii::$app->get('elasticsearch');<br>}
接着定义 mapping() 方法——这是全文搜索生效的核心。若省略此方法,Elasticsearch 将使用动态 mapping,中文字段默认为 text 类型但无分词器,搜索时无法匹配单字或词组。
示例(适配中文 IK 分词器):
public static function mapping() {<br> return [<br> 'properties' => [<br> 'title' => ['type' => 'text', 'analyzer' => 'ik_max_word', 'search_analyzer' => 'ik_smart'],<br> 'content' => ['type' => 'text', 'analyzer' => 'ik_max_word', 'search_analyzer' => 'ik_smart'],<br> 'status' => ['type' => 'integer'],<br> ],<br> ];<br>}
注意:ik_max_word 用于索引阶段切分出尽可能多的词,ik_smart 用于搜索阶段减少误匹配;若未安装 ik 插件,此配置将导致索引创建失败。
创建索引并写入测试数据
在控制器或命令行中执行以下操作:
第一步:调用 ArticleSearch::createIndex() 创建索引(自动应用 mapping);
第二步:使用 save() 写入文档,例如:
$model = new ArticleSearch();<br>$model->title = 'Yii2 集成 Elasticsearch 全文检索';<br>$model->content = '本教程演示如何在 Yii2.0.55 中配置 Elasticsearch 实现中文搜索';<br>$model->status = 1;<br>$model->save();
第三步:强制刷新索引使文档立即可查:ArticleSearch::refresh(); —— 不执行这一步,新写入文档可能延迟数秒才被检索到。
执行全文检索查询
方法一:使用 query() 构建 DSL 查询
$query = ArticleSearch::find()<br> ->query(['match' => ['title' => 'Yii2']])<br> ->limit(10);<br>$models = $query->all();
方法二:使用 rawQuery() 直接传入完整 JSON DSL(适合复杂条件)
$dsl = [<br> 'query' => [<br> 'multi_match' => [<br> 'query' => '全文检索',<br> 'fields' => ['title^3', 'content']<br> ],<br> ],<br> 'highlight' => [<br> 'fields' => ['title' => new \stdClass(), 'content' => new \stdClass()]<br> ],<br>];<br>$models = ArticleSearch::find()->rawQuery($dsl)->all();
注意:highlight 字段需传入空对象而非空数组,否则高亮不生效;multi_match 中的 ^3 表示 title 字段权重是 content 的三倍。











