搭建 Elasticsearch 容器
laradock 中支持 Elasticsearch,直接搭建就可以,省去了诸多麻烦
- 切换到
laradock
目录 docker-compose build elasticsearch
docker-compose up -d elasticsearch
- 进入容器中
docker-compose exec elasticsearch bash
- 安装 ik 插件,注意要和 elasticsearch 版本相同,在
elasticsearch/Dockerfile
中可以查看版本./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.6.0/elasticsearch-analysis-ik-6.6.0.zip
- 退出容器后重启
docker-compose restart elasticsearch
导语
全文搜索是很重要的功能,实现的方式也有很多种。以下通过 Laravel Scout 和 Elasticsearch 实现。先来看下各自的介绍
Laravel Scout 为 Eloquent 模型全文搜索实现提供了简单的、基于驱动的解决方案。通过使用模型观察者,Scout 会自动同步更新模型记录的索引。
Elasticsearch是一个基于Lucene库的搜索引擎。它提供了一个分布式、支持多租户的全文搜索引擎,具有HTTP Web接口和无模式 JSON 文档。Elasticsearch是用 Java 开发的,并在 Apache 许可证下作为开源软件发布。官方客户端在Java、.NET(C#)、 PHP 、 Python 、Apache Groovy、 Ruby 和许多其他语言中都是可用的。[5]根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr,也是基于Lucene。
新建测试数据
新建 fake_articles 用来测试
新建模型以及数据迁移 php artisan make:model Models/FakeArticle -m
在数据迁移中 database/migrations/2019_06_13_095420_create_fake_articles_table.php 编辑如下
public function up()
{
Schema::create('fake_articles', function (Blueprint $table) {
$table->increments('id');
$table->string('author', 20)->comment('作者');
$table->string('title', 200)->comment('标题');
$table->text('content')->comment('内容');
$table->timestamps();
});
}
运行迁移 php artisan migrate
新建数据填充 php artisan make:seeder FakeArticlesSeeder
填充几条中文数据,以便后续测试
public function run()
{
\App\Models\FakeArticle::insert([
[
'author' => '王二',
'title' => '黄金时代',
'content' => '那一天我二十一岁,在我一生的黄金时代,我有好多奢望。我想爱,想吃,还想在一瞬间变成天上半明半暗的云,后来我才知道,生活就是个缓慢受锤的过程,人一天天老下去,奢望也一天天消逝,最后变得像挨了锤的牛一样。可是我过二十一岁生日时没有预见到这一点。我觉得自己会永远生猛下去,什么也锤不了我。',
'created_at' => now(),
'updated_at' => now(),
],
['author' => '陈辉',
'title' => '绿毛水怪',
'content' => '大团的蒲公英浮在街道的河流口,吞吐着柔软的针一样的光,我们好像在池塘的水底,从一个月亮走向另一个月亮。',
'created_at' => now(),
'updated_at' => now(),
],
['author' => '迅哥',
'title' => '社戏',
'content' => '两岸的豆麦和河底的水草所发散出来的清香,夹杂在水气中扑面的吹来;月色便朦胧在这水气里。淡黑的起伏的连山,仿佛是踊跃的铁的兽脊似的,都远远的向船尾跑去了,但我却还以为船慢。他们换了四回手,渐望见依稀的赵庄,而且似乎听到歌吹了,还有几点火,料想便是戏台,但或者也许是渔火。',
'created_at' => now(),
'updated_at' => now(),
]
]);
}
运行填充 php artisan db:seed --class=FakeArticlesSeeder
安装扩展包以及配置
composer require tamayo/laravel-scout-elastic
- 在
config/app.php
中providers
添加Laravel\Scout\ScoutServiceProvider::class
和ScoutEngines\Elasticsearch\ElasticsearchProvider::class,
- 发布配置文件
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
- 在
config/scout.php
添加
'elasticsearch' => [
'index' => env('ELASTICSEARCH_INDEX', 'laravel'),
'hosts' => [
env('ELASTICSEARCH_HOST', 'http://localhost'),
],
],
- 编辑
.env
文件,所以添加如下配置项
SCOUT_DRIVER=elasticsearch
ELASTICSEARCH_INDEX=laravel_index
ELASTICSEARCH_HOST=elasticsearch #因为环境是 laradock
修改模型配置
修改 app/Models/FakeArticle.php
文件如下
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class FakeArticle extends Model
{
Use Searchable;
/**
* 需要查询的字段
* @return array
*/
public function toSearchableArray()
{
return $this->only('author', 'title', 'content');
}
}
设置 Elasticsearch 分词策略
这一步是花费时间最多的地方,查的资料要么是过时的,要么根本不能运行。最终根据这篇文章修改而来。
关于 ik 分词以及 ik_max_word
和 ik_smart
的区别,不在这里赘述了,可以看下这篇文章。
新建文件 php artisan make:command InitEs
,编辑如下
<?php
namespace App\Console\Commands;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
class InitEs extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'init:es';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Elasticsearch 初始化配置';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$client = new Client();
$this->createTemplate($client);
$this->createIndex($client);
}
/**
* 创建模板 see https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic-templates.html
* @param Client $client
*/
private function createTemplate(Client $client)
{
$url = config('scout.elasticsearch.hosts')[0] . ':9200/_template/template_1';
$client->put($url, [
'json' => [
'template' => config('scout.elasticsearch.index'),
'settings' => [
'number_of_shards' => 1,
],
'mappings' => [
'_default_' => [
'dynamic_templates' => [ // 动态映射模板
[
'string_fields' => [ // 字段映射模板的名称,一般为"类型_fields"的命名方式
'match' => '*', // 匹配的字段名为所有
'match_mapping_type' => 'string', // 限制匹配的字段类型,只能是 string 类型
'mapping' => [ // 字段的处理方式
'type' => 'text', // 字段类型限定为 string
'analyzer' => 'ik_max_word', // 字段采用的分析器名,默认值为 standard 分析器
'fields' => [
'raw' => [
'type' => 'keyword',
'ignore_above' => 256, // 字段是索引时忽略长度超过定义值的字段。
]
],
],
],
],
],
],
],
],
]);
}
/**
* 创建索引
* @param Client $client
*/
private function createIndex(Client $client)
{
$url = config('scout.elasticsearch.hosts')[0] . ':9200/' . config('scout.elasticsearch.index');
$client->put($url, [
'json' => [
'settings' => [
'refresh_interval' => '5s',
'number_of_shards' => 1, // 分片为
'number_of_replicas' => 0, // 副本数
],
'mappings' => [
'_default_' => [
'_all' => [
'enabled' => false, // 是否开启所有字段的检索
],
],
],
],
]);
}
}
使用
php artisan init:es
php artisan scout:import "App\Models\FakeArticle"
[图片上传失败...(image-13bc2c-1576134718365)]
- 搜索的时候使用
FakeArticle::search('搜索词')->get();
结语
测试后没有问题,可以正常搜索。更多的方法参考这里。
参考资料:Elastic Driver for Laravel Scout、Laravel Scout + Elasticsearch + ik 分词
网友评论