Laravel使用es

1.es是什么呢?

ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

2.安装

3.引入

composer require laravel/scout
composer require matchish/laravel-scout-elasticsearch

4.配置

生成 Scout 配置文件 (config/scout.php)

php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"

5.指定 Scout 驱动

第一种:在.env 文件中指定(建议)
SCOUT_DRIVER=Matchish\ScoutElasticSearch\Engines\ElasticSearchEngine
ELASTICSEARCH_HOST=127.0.0.1:9200 //指定ip
第二种:在 config/scout.php 直接修改默认驱动
'driver' => env('SCOUT_DRIVER', 'Matchish\ScoutElasticSearch\Engines\ElasticSearchEngine')

6.注册服务

修改config/app.php文件

'providers' => [
     // Other Service Providers
     \Matchish\ScoutElasticSearch\ElasticSearchServiceProvider::class
],

7.清除配置缓存

php artisan config:clear

至此 laravel 已经接入 Elasticsearch

8.实际业务中使用

通过博客右上角的搜索框可以搜索到与关键词相关的文章,从以下几点匹配

  • 文章内容

  • 文章标题

  • 文章标签
    涉及到 2 张 Mysql 表 以及字段

  • article
    title
    tags

  • article_content
    content
    为文章配置 Elasticsearch 索引
    创建索引配置文件(config/elasticsearch.php)

1). 创建config/elasticsearch.php,配置字段映射
<?php
return [
 'indices' => [
     'mappings' => [
         'blog-articles' => [
             "properties"=>  [
                 "content"=>  [
                     "type"=>  "text",
                     "analyzer"=>  "ik_max_word",
                     "search_analyzer"=>  "ik_smart"
                 ],
                 "tags"=>  [
                     "type"=>  "text",
                     "analyzer"=>  "ik_max_word",
                     "search_analyzer"=>  "ik_smart"
                 ],
                 "title"=>  [
                     "type"=>  "text",
                     "analyzer"=>  "ik_max_word",
                     "search_analyzer"=>  "ik_smart"
                 ]
             ]
         ]
     ]
 ],
];
  • analyzer:字段文本的分词器
    • search_analyzer:搜索词的分词器
    • 根据具体业务场景选择 (颗粒小占用资源多,一般场景 analyzer 使用 ik_max_word,search_analyzer 使用 ik_smart):
      • ik_max_word:ik 中文分词插件提供,对文本进行最大数量分词
        laravel天下无敌 -> laravel,天下无敌 , 天下 , 无敌
      • ik_smart: ik 中文分词插件提供,对文本进行最小数量分词
        laravel天下无敌 -> laravel,天下无敌
2). 配置文章模型
  • 引入 Laravel Scout
 namespace App\Models\Blog;

 use Laravel\Scout\Searchable;

 class Article extends BlogBaseModel
 {
     use Searchable;
 }
  • 指定索引 (刚刚配置文件中的 elasticsearch.indices.mappings.blog-articles)
 /**
  * 指定索引
  * @return string
  */
 public function searchableAs()
 {
     return 'blog-articles';
 }
  • 设置导入索引的数据字段
 /**
  * 设置导入索引的数据字段
  * @return array
  */
 public function toSearchableArray()
 {
     return [
         'content' => ArticleContent::query()
             ->where('article_id',$this->id)
             ->value('content'),
         'tags'    => implode(',',$this->tags),
         'title'   => $this->title
     ];
 }
  • 指定 搜索索引中存储的唯一 ID
 /**
  * 指定 搜索索引中存储的唯一ID
  * @return mixed
  */
 public function getScoutKey()
 {
     return $this->id;
 }

 /**
  * 指定 搜索索引中存储的唯一ID的键名
  * @return string
  */
 public function getScoutKeyName()
 {
     return 'id';
 }
3). 数据导入

其实是将数据表中的数据通过 Elasticsearch 导入到 Lucene Elasticsearch 是 Lucene 的封装,提供了 REST API 的操作接口

  • 一键自动导入:php artisan scout:import
  • 导入指定模型:php artisan scout:import ${model}
php artisan scout:import "App\Models\Blog\Article"

如果提示内存溢出,修改/bin/elasticsearch文件,添加

-Xmx4g 
-Xms4g

查看$ curl -XGET http://localhost:9200/blog-articles/_mapping?pretty

{
  "blog-articles_1598362919" : {
    "mappings" : {
      "properties" : {
        "__class_name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "content" : {
          "type" : "text",
          "analyzer" : "ik_max_word",
          "search_analyzer" : "ik_smart"
        },
        "tags" : {
          "type" : "text",
          "analyzer" : "ik_max_word",
          "search_analyzer" : "ik_smart"
        },
        "title" : {
          "type" : "text",
          "analyzer" : "ik_max_word",
          "search_analyzer" : "ik_smart"
        }
      }
    }
  }
}
4).测试
  • 创建一个测试命令行
php artisan make:command ElasticTest
  • 代码
<?php

namespace App\Console\Commands;

use App\Models\Blog\Article;
use App\Models\Blog\ArticleContent;
use Illuminate\Console\Command;
use Illuminate\Support\Carbon;

class ElasticTest extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'elasticsearch {query}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'elasticsearch test';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        //
        $startTime = Carbon::now()->getPreciseTimestamp(3);
        $articles = Article::search($this->argument('query'))->get()->toArray();
        $userTime = Carbon::now()->getPreciseTimestamp(3) - $startTime;
        echo "耗时(毫秒):{$userTime} \n";

        //content在另外一张表中,方便观察测试 这里输出
        if(!empty($articles)) {
            foreach($articles as &$article) {
                $article = ArticleContent::query()->where('article_id',$article['id'])->value('content');
            }
        }

        var_dump($articles);

    }
}
  • 测试php artisan elasticsearch 周杰伦

  • 复杂查询

    • 例如:自定义高亮显示
//ONGR\ElasticsearchDSL\Highlight\Highlight 
ArticleModel::search($query,function($client,$body) {
            $higlight = new Highlight();
            $higlight->addField('content',['type' => 'plain']);
            $higlight->addField('title');
            $higlight->addField('tags');
            $body->addHighlight($higlight);
            $body->setSource(['title','tags']);
            return $client->search(['index' => (new ArticleModel())->searchableAs(), 'body' => $body->toArray()]);
        })->raw();        

参考:https://learnku.com/articles/48630

posted @ 2022-12-12 23:57  成文的博客  阅读(1079)  评论(2编辑  收藏  举报