Yii 2.0 集成 ElasticSearch 教程 [ 2.0 版本 ]
前几天做了一个模块,大数据的搜索,其实也不是特别大,组合起来差不多800万左右,用的是mysql数据库,需求有这么变态的两点;
需要按照地址去搜索
按照起止时间去搜索
别的不说,就这两条,mysql也就只能用like了吧,而且地址需要用%xx%这种,压根用不到索引,结果可想而知,服务器直接崩了;
和老大讨论了下,决定采用ElasticSearch做全文搜索,由于之前看过一点点(其实就是自己瞎玩),所以学起来不是太难,但是学过和做过东西是不一样的两个概念;所以写下这篇文章记录下需要注意的点,而且也是为了弥补百度ElaticSearch资料空白;
首先就是框架的选用,这里我选用的是Yii2.0,这里吐槽下Yii2.0的文档,中文文档里压根就没有ElasticSearch,打开直接404,
所以我打开了英文文档和github,这才找到了资料;
- 安装扩展
composer require --prefer-dist yiisoft/yii2-elasticsearch
- main.php中引入
'elasticsearch' => [
'class' => 'yii\elasticsearch\Connection',
'nodes' => [
['http_address' => '127.0.0.1:9200'],
],
],
- 建立model
<?php
namespace app\models;
use yii\elasticsearch\ActiveRecord;
class Merge extends ActiveRecord
{
//需要返回的字段
public function attributes()
{
return ['contactphone','xxx','xxx']; //其实这里就是你要查询的字段,你要查什么写什么字段就好了
}
//索引
public static function index()
{
return 'visit_patient_test_index';
}
//文档类型
public static function type()
{
return 'visit_patient_type';
}
//这个就是第二步配置的组件的名字(key值)
public static function getDb()
{
return \Yii::$app->get('elasticsearch');
}
}
- 控制器
$merge = new Merge();
$query = $merge::find()->all(); //这句话是查询所有的数据(但是es本身有限制,所以只会查出来10条,下面我会说怎么查更多数据)
这里可能会有如下错误
Elasticsearch Database Exception
解决方案如下:
打开 yii2-advanced/vendor/yiisoft/yii2-elasticsearch/Connection.php
这个文件,修改扩展的源码
CURLOPT_HTTPHEADER => ['Expect:'],
这一行改成
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'Content-Type: application/json'
],
解下来就是全文搜索的重点了;
mysql这种数据库不支持全文搜索,一搜就崩;上次服务器搞崩了凌晨到维护好;
这里全文搜索有以下几个坑,需要注意
如果你按照时间搜索的话,记得字段的类型,一定要指定为date类型(或者int总之不要text),不要问我怎么知道的,表不是我建的,但是坑了我一下午,就是不能按照时间范围搜索;
单搜索词和多个搜索词写法不一样,需要注意;
es搜索,默认返回10条语句,但是你可以使用limit()去限制查询出的结果,比如你希望100条,你就limit(100),但是上限是1w;
代码开始:
- 时间范围搜索,xxx是你要搜的字段,start是开始时间,end是结束时间,注意xxx的字段类型一定是date,xxx和start,end结构一致;
$query_arr = [
"bool" => [
"filter" => [
"range" => [
"xxx" => [
"from" => $start,
"to" => $end
]
]
]
],
];
- 单关键词搜索,你只需要讲match对应你要搜索的数组就可以
$query_arr = [
"bool" => [
"must" => [
"match" => ["name"=>"bht"]
]
],
];
- 多关键词搜索,should相当于or,如果想用and,可以改成must
$query_arr = [
"bool" => [
"should" => [
['match' => ["name" => "bht"]],
['match' => ["sex" => "男"]],
['match' => ["age" => "24"]],
['match' => ["add" => "山东济南"]]
],
],
];
- 范围搜索,对于数字,用gl(great than大于) , lt(less than) , gle(大于等于),lte(小于等于)
$query_arr = [
"bool" => [
"filter" => [
"range" => [
"xxx" => [
"gle" => 10,
"lte" => 20
]
]
]
],
];
- 排序 desc和asc
$sort = ['xxx' => ['order' => 'desc']]
- 短语匹配
就是把第3条中的match改成match_phrase,在执行短语匹配查询时,ElasticSearch引擎首先分析(analyze)查询字符串,从分析后的文本中构建短语查询,这意味着必须匹配短语中的所有分词,并且保证各个分词的相对位置不变;个人感觉比精确匹配更好用
以上条件写好后,按照如下,就可以搜索了
$merge = new Merge();
$merge::find()->query($query_arr)->orderBy($sort)->asArray()->all()
但是搜索出来的数目只有10条,如果你的数据多于10条,请加limit(你想显示的条数)
query->orderBy($sort)->asArray()->limit(100)->all()
希望能对大家有所帮助,详细资料请查看机智的Coder
薄洪涛
最后登录:2022-01-28
在线时长:14小时22分
- 粉丝4
- 金钱75
- 威望40
- 积分615
共 4 条评论
请问一下,我使用的是mysql,怎样用这个es 关联到我的mysql 数据表,直接按照你这个来也不行啊,请指点一下呗
你想把ES的索引当作一张表跟mysql的表做连表操作?怕是不可能哦
这个要同步到es里面去 有这种mysql同步的组件
这个我真没关联过,这属于跨库关联查询了吧
model 是最消耗性能的,后台可以用但是如果是接口的话真的不能那么用吧
具体的性能我没测试,不过我觉得,model的性能损耗应该很小,实在不行就直接请求es提供的接口呗
1.安装elasticsearch的时候,需要用java环境吗,需要再新安装分词吗
2.我写入到yii框架里边查询无结果,在postman里边直接通过地址localhost:9200/_search查询,传入参数
`{
"query": {
"match": { "title": { "query": "图书馆" } }
}
}`
是可以搜索到结果的
1.es安装是需要java环境的
2.请检查yii写法是否正确
可以直接用Query来实现搜索吗?