Laradock-elasticsearch配置

搭建 Elasticsearch 容器

laradock 中支持 Elasticsearch,直接搭建就可以,省去了诸多麻烦

  1. 切换到 laradock 目录
  2. docker-compose build elasticsearch
  3. docker-compose up -d elasticsearch
  4. 进入容器中 docker-compose exec elasticsearch bash
  5. 安装 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
Laravel 基于 Scout 配置实现 Elasticsearch (一)- 准备工作
  1. 退出容器后重启 docker-compose restart elasticsearch

导语

全文搜索是很重要的功能,实现的方式也有很多种。以下通过 Laravel Scout 和 Elasticsearch 实现。先来看下各自的介绍

Laravel Scout 为 Eloquent 模型全文搜索实现提供了简单的、基于驱动的解决方案。通过使用模型观察者,Scout 会自动同步更新模型记录的索引。

Elasticsearch是一个基于Lucene库的搜索引擎。它提供了一个分布式、支持多租户的全文搜索引擎,具有HTTP Web接口和无模式 JSON 文档。Elasticsearch是用 Java 开发的,并在 Apache 许可证下作为开源软件发布。官方客户端在Java、.NET(C#)、 PHPPython 、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

安装扩展包以及配置

  1. composer require tamayo/laravel-scout-elastic
  2. config/app.phpproviders 添加 Laravel\Scout\ScoutServiceProvider::classScoutEngines\Elasticsearch\ElasticsearchProvider::class,
  3. 发布配置文件 php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
  4. config/scout.php 添加
'elasticsearch' => [
    'index' => env('ELASTICSEARCH_INDEX', 'laravel'),
    'hosts' => [
        env('ELASTICSEARCH_HOST', 'http://localhost'),
    ],
],
  1. 编辑 .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_wordik_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, // 是否开启所有字段的检索
                        ],
                    ],
                ],
            ],
        ]);
    }
}

使用

  1. php artisan init:es
  2. php artisan scout:import "App\Models\FakeArticle"

[图片上传失败...(image-13bc2c-1576134718365)]

  1. 搜索的时候使用 FakeArticle::search('搜索词')->get();

结语

测试后没有问题,可以正常搜索。更多的方法参考这里


参考资料:Elastic Driver for Laravel ScoutLaravel Scout + Elasticsearch + ik 分词

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355