其他分享
首页 > 其他分享> > Laravel + Elasticsearch 实现中文搜索

Laravel + Elasticsearch 实现中文搜索

作者:互联网

Elasticsearch


Elasticsearch 是一个基于 Apache Lucene (TM) 的开源搜索引擎,无论在开源还是专有领域,Lucene 可 以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。

但是,Lucene 只是一个库。想要发挥其强大的作用,你需使用 Java 并要将其集成到你的应用中。Lucene 非常复杂,你需要深入的了解检索相关知识来理解它是如何工作的。

Elasticsearch 也是使用 Java 编写并使用 Lucene 来建立索引并实现搜索功能,但是它的目的是通过简单连贯的 RESTful API 让全文搜索变得简单并隐藏 Lucene 的复杂性。

不过,Elasticsearch 不仅仅是 Lucene 和全文搜索引擎,它还提供:

分布式的实时文件存储,每个字段都被索引并可被搜索

实时分析的分布式搜索引擎

可以扩展到上百台服务器,处理 PB 级结构化或非结构化数据

而且,所有的这些功能被集成到一台服务器,你的应用可以通过简单的 RESTful API、各种语言的客户端甚至命令行与之交互。上手 Elasticsearch 非常简单,它提供了许多合理的缺省值,并对初学者隐藏了复杂的搜索引擎理论。它开箱即用(安装即可使用),只需很少的学习既可在生产环境中使用。

Elasticsearch 在 Apache 2 license 下许可使用,可以免费下载、使用和修改。

ElasticSearch 安装

官方下载地址:

https://www.elastic.co/cn/downloads/elasticsearch

安装过程不再赘述,网上一堆教程哈。

我用的是Windows系统,安装完成后,用cmd进入es安装目录下的bin文件夹,执行 elasticsearch 启动es服务,

访问127.0.0.1:9200,出现以下界面为安装成功

IK 分词器安装

ElasticSearch 主要是用于自己 blog 或者公众号文章的搜索使用,所以需要选择一个中文分词器配合使用,这里刚开始推荐使用 IK 分词器,下面开始安装对应 ElasticSearch 版本 (7.15.1) 一致的插件:

https://github.com/medcl/elasticsearch-analysis-ik/releases

下载完成后,解压插件到文件夹 es安装目录/plugins/ik

重启elasticsearch

用postman 试一下分词效果,

结合 Laravel


虽然 Elasticsearch 官方提供了对应的 PHP 版本的插件,但我们还是希望和 Laravel 结合的更紧密些,所以这里选择和 Scout 结合使用,具体用到了 babenkoivan/elastic-scout-driver 插件

github地址:https://github.com/babenkoivan/elastic-scout-driver

我看到网上的教程都用的是laravel-scout-elastic 这个软件包,但是我用的时候发现他不支持laravel8,所以我找到了他的完美替代品“elastic-scout-drive”。

安装 elasticsearch-php 客户端

composer require elasticsearch/elasticsearch

安装 elastic-scout-driver 软件包

composer require babenkoivan/elastic-scout-driver

请注意,这个库只是 Laravel Scout 的驱动程序,不要忘记预先安装它:

composer require laravel/scout

安装Scout后,使用发布其配置文件

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

发布完成后,编辑config/scout.php

// config/scout.php
...
    // Set your driver to elasticsearch
    'driver' => env('SCOUT_DRIVER', 'elastic'),
...
    /*
    |--------------------------------------------------------------------------
    | Elasticsearch Configuration
    |--------------------------------------------------------------------------
    |
    | Here you may configure your Elasticsearch settings.
    |
    */
    'elasticsearch' => [
        'hosts' => [
            env('ELASTICSEARCH_HOST', 'localhost'),
            // [
            //     'host'   => env('ELASTICSEARCH_HOST', 'localhost'),
            //     'port'   => env('ELASTICSEARCH_PORT', '9200'),
            //     'scheme' => env('ELASTICSEARCH_SCHEME', 'https'),
            //     'path'   => env('ELASTICSEARCH_PATH', '/elastic'),
            //     'user'   => env('ELASTICSEARCH_USER', 'username'),
            //     'pass'   => env('ELASTICSEARCH_PASS', 'password'),
            // ]
        ],
    ]
...

在.env 里加入ELASTICSEARCH_HOST地址

ELASTICSEARCH_HOST=127.0.0.1:9200

创建索引#

创建索引有好几种方式,可以用postMan

或者用Laravel 自带的 Artisan 命令行功能。

php artisan make:command ESOpenCommand

根据官网提示,我们可以在 ESOpenCommand 上向 Elasticsearch 服务器发送 PUT 请求,这里借助 Elasticsearch 提供的 PHP 插件,在我们上面的过程中,已经安装了 Elasticsearch PHP 插件

下面就可以借助插件,创建我们的 Index,直接看代码:

<?php

namespace App\Console\Commands;

use Elasticsearch\ClientBuilder;
use Illuminate\Console\Command;

class ESOpenCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'es:create';

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

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

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $host = config('scout.elasticsearch.hosts');
        $index = 'bloges';
        $client = ClientBuilder::create()->setHosts($host)->build();

        if ($client->indices()->exists(['index' => $index])) {
            $this->warn("Index {$index} exists, deleting...");
            $client->indices()->delete(['index' => $index]);
        }

        $this->info("Creating index: {$index}");

        return $client->indices()->create([
            'index' => $index,
            'body' => [
                'settings' => [
                    'number_of_shards' => 1,
                    'number_of_replicas' => 0
                ],
                'mappings' => [
                    '_source' => [
                        'enabled' => true
                    ],
                    'properties' => [
                        'id' => [
                            'type' => 'long'
                        ],
                        'title' => [
                            'type' => 'text',
                            'analyzer' => 'ik_max_word',
                            'search_analyzer' => 'ik_max_word'
                        ],
                        'content' => [
                            'type' => 'text',
                            'analyzer' => 'ik_max_word',
                            'search_analyzer' => 'ik_max_word'
                        ]
                    ],
                ]
            ]
        ]);
    }
}

执行一下php artisan 命令 php artisan es:create

好了,我们已经成功创建index ,验证一下

用postman 访问 127.0.0.1:9200/_cat/indices 查看所有index

可以看到bloges 索引已经成功创建,注意黄色圆圈的数字,他代表这个索引里面有多少条数据。之后可以验证数据是否导入成功。

OK,配置完成后我们开始随便建个Controller 和 model

php artisan make:model Blog -mc

迁移文件

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateBlogsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('blogs', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('content');
            $table->integer('red_num');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('blogs');
    }
}

model

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class Blog extends Model
{
    use HasFactory;
    use Searchable;
    protected $table = 'blogs';

    public function searchableAs()
    {
        return 'bloges';
    }
    public function toSearchableArray()
    {
        $data = [
            'id' => $this->id,
            'title' => $this->title,
            'content' => $this->content
        ];
        return $data;
    }
}

model 里注意searchableAs 这里写索引的名称,toSearchableArray 里写可以用于搜索的字段。具体可以参考scout的文档 https://learnku.com/docs/laravel/9.x/scout/12273

然后我们随便复制粘贴一些数据到blog表里。

Scout 提供了 Artisan 命令 import 用来导入所有已存在的记录到搜索索引中。

php artisan scout:import "App\Models\Blog"

接下来在controller里面

 $orders = Blog::search('树叶 过来 业绩')->raw();
//或者
 $orders = Blog::search('树叶 过来 业绩')->get();
//raw 输出原始格式,get 输出 Eloquent Model

dd($orders);
     

看下结果

大功告成!

参考:

https://learnku.com/articles/40289

https://blog.csdn.net/jam00/article/details/52983056

https://www.cnblogs.com/mmmzh/p/11599678.html

标签:Laravel,index,中文搜索,scout,Elasticsearch,env,elasticsearch,ELASTICSEARCH
来源: https://www.cnblogs.com/houying/p/15963542.html