Laravel-Docker 环境下使用 Elasticsearch 总结
Elasticsearch提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java语言开发的,能够达到实时搜索,稳定,可靠,快速,安装使用方便。
参考
环境需求
- PHP >= 7.0
- ext-json >=1.3.7
- docker下lnmp + Elasticsearch
继续阅读需具备以下知识、能力
- composer
- laravel迁移
- docker(不会需手动安装java环境)
- 动手能力
Begin!
准备工作
- 假设你laravel环境已经搭建好,访问 / 看到laravel默认页面。
- 本地lnmp + Elasticsearch 已经搭建并运行。
- curl本地Elasticsearch响应正常。
安装官方提供的扩展包
composer require elasticsearch/elasticsearch:~6.0
生成控制器、迁移文件
php artisan make:model Article -mc
表字段&生成表
public function up()
{
Schema::create('articles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('author')->comment('作者;')->nullable();
$table->string('title')->comment('书名')->nullable();
$table->text('body')->comment('内容')->nullable();
$table->string('countries')->comment('国家')->nullable();
$table->string('desc')->comment('简介')->nullable();
$table->timestamps();
});
}
// 生成表
php artisan migrate
填充数据
php artisan make:seeder ArticleTableSeeder
public function run()
{
\Illuminate\Support\Facades\DB::table('articles')->insert([
[
'author' => '尼古拉·奥斯特洛夫斯基',
'title' => '钢铁是怎么练成的',
'body' => '',
'countries' => '苏联',
'desc' => '本书是一部闪烁着崇高理想主义光芒的半自传体长篇小说,小说成功地塑造了保尔·柯察金这一无产阶级英雄形象,以生动而又富于生活气息的语言、震撼人心的精神力量,展现了保尔·柯察金的生活和情感世界,成为了'
]
...more
]);
}
调用 Seeders
在 DatabaseSeeder
类中,你可以使用 call
方法来运行其他的 seed 类。使用 call
方法可以将数据填充拆分成多个文件,这样就不会使单个 seeder 变得非常大。只需简单传递要运行的 seeder 类名称即可:
public function run()
{
$this->call([
ArticleTableSeeder::class,
]);
}
运行 Seeders
完成 seeder 类的编写之后,你可能需要使用 dump-autoload
命令重新生成 Composer 的自动加载器:
composer dump-autoload
接着就可以使用 Artisan 命令 db:seed
来填充数据库了。默认情况下,db:seed
命令将运行 DatabaseSeeder
类,这个类可以用来调用其它 Seed 类。不过,你也可以使用 --class
选项来指定一个特定的 seeder 类:
php artisan db:seed
php artisan db:seed --class=ArticleTableSeeder
数据检查
开始干货
绑定别名,方便后面使用
// app/Providers/AppServiceProvider.php
use Elasticsearch\ClientBuilder;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
$this->registerEsService();
}
protected function registerEsService()
{
$this->app->singleton('es',function(){
$host = [
// 容器内部通信端口,docker知识
'elasticsearch:9200'
];
return ClientBuilder::create()->setHosts($host)->build();
});
}
}
创建索引(和我们使用mysql一样创建表结构) es 官方文档字段
protected $index = 'article_index'; // 索引名字
protected $type = 'article_type'; // 索引类型
public function createIndex()
{
$result = ((new EsService)->createIndex());
dd($result);
// array:3 [▼
// "acknowledged" => true
// "shards_acknowledged" => true
// "index" => "article_index"
// ]
}
public function createIndex()
{
// 创建索引
$params = [
'index' => $this->index,
'body' => [
'settings' => [
'number_of_shards' => 1,
'number_of_replicas' => 2
],
'mappings' => [
$this->type => [
'_source' => [
'enabled' => true
],
'properties' => [
'created_at' => [
'type' => 'date',
"format" => "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||yyyy-MM||yyyy/MM/dd||yyyy/MM||strict_date_optional_time||epoch_millis"
],
'author' => [
'type' => 'text',
],
'body' => [
'type' => 'text',
],
'countries' => [
'type' => 'text',
],
'desc' => [
'type' => 'text',
],
]
]
]
]
];
return app('es')->indices()->create($params);
}
向es写入数据
public function run()
{
$ids = [4,5,6];
$data = Article::whereIn('id',$ids)->get();
$result = (new EsService)->add($data,['created_at']);
dd($result); // 只需关注 errors
// array:3 [▼
// "took" => 15
// "errors" => false
// "items" => array:3 [▼
// 0 => array:1 [▼
// "index" => array:9 [▼
// "_index" => "article_index"
// "_type" => "article_type"
// "_id" => "8yik83EBzOhuf1N0cyBT"
// "_version" => 1
// "result" => "created"
// "_shards" => array:3 [▼
// "total" => 3
// "successful" => 1
// "failed" => 0
// ]
// "_seq_no" => 0
// "_primary_term" => 1
// "status" => 201
// ]
// ]
// 1 => array:1 [▼
// "index" => array:9 [▶]
// ]
// 2 => array:1 [▶]
// ]
// ]
}
public function add($data,$field = [])
{
foreach ($data as $k => $v){
$temp = [];
foreach ($field as $kk => $vv){
$temp[$vv] = $v->$vv;
}
// 不传入_id会帮我们自动生成
$params['body'][] = [
'index' => [
'_index' => $this->index,
'_type' => $this->type
]
];
$params['body'][] = $temp;
}
$responses = app('es')->bulk($params);
dd($responses);
}
搜索数据
1.搜索全部数据
public function search()
{
$type = 'all';
$data = (new EsService)->search($type);
dd($data);
}
public function search($type,$conditions = [])
{
switch ($type){
case 'all':
$params = [
'index' => $this->index,
'type' => $this->type,
];
$response = app('es')->search($params);
return $response;
}
}
2.搜索某个字段的数据(针对某个字段)
注意:这个时候如果有个作者名字是:林林汉达也会被搜索到。
手动添加一条数据作者为:林林汉达,调用上面到run()方法写入es,查看下结果。
try
public function search()
{
$type = 'q';
$q = [
'query' => [
'match' => [
// 搜索作者字段包含林汉达的
'author' => '林汉达'
]
]
];
$data = (new EsService)->search($type,$q);
dd($data);
}
public function search($type,$conditions = [])
{
$params = [
'index' => $this->index,
'type' => $this->type,
];
switch ($type){
case 'q':
$params['body'] = $conditions;
return app('es')->search($params);
}
}
3.搜索国家为中国的数据
注意生成索引的时候用的
keyword
,解决上面林林汉达
问题。
4. 搜索排序
这个时候我们想按照时间越大大排在前面(没有
_score
的影响下 )(倒序)
public function search()
{
/*按时间倒序排序*/
$type = 'sort';
$q = [
"sort" => [
"created_at" => 'desc'
]
];
$data = (new EsService)->search($type,$q);
dd($data);
}
public function search($type,$conditions = [])
{
$params = [
'index' => $this->index,
'type' => $this->type,
];
switch ($type){
case 'sort':
$params['body'] = $conditions;
return app('es')->search($params);
}
}
可以看到,es都搜索非常灵活,也可以带条件组合搜索。es中文文档
分页
方式1. size搜索数量,from跳过第几个
public function search()
{
$type = 'page';
$q = [
'size' => 1,
'from' => 1,
"body" => [ // 条件,可以去掉
"query" => [
"match_all" => new \stdClass()
]
]
];
$data = (new EsService)->search($type,$q);
dd($data);
}
public function search($type,$conditions = [])
{
$params = [
'index' => $this->index,
'type' => $this->type,
];
switch ($type){
case 'page':
$c = array_merge($params,$conditions);
return app('es')->search($c);
}
}
方式2
使用游标,比较简单,复制官方例子就可以跑起来,不在示范。
删除索引(危险,不是单条删除,类似mysql删库)
public function deleteIndex()
{
$result = ((new EsService)->deleteIndex());
dd($result);
// array:1 [▼
// "acknowledged" => true
// ]
}
public function deleteIndex($index = '')
{
$deleteParams = [
'index' => $index == '' ? $this->index : $index,
];
return app('es')->indices()->delete($deleteParams);
}
总结: Elasticsearch PHP Sdk对使用者非常友好,强烈建议使用者 先快速看下es中文版文档(1-2个小时),在看下Elasticsearch PHP Sdk(20分钟)即可上手使用。
最后特别谢谢 DNMP(Docker + Nginx + MySQL + PHP7/5 + Redis)是一款全功能的LNMP一键安装程序, 让使用如此简单。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: