当前位置: BoxPHP > PHP开发 > 如何在 Laravel 中用 ZincSearch 实现站内搜索引擎

如何在 Laravel 中用 ZincSearch 实现站内搜索引擎

更新时间:2025-03-12 14:17:15 所属分类: PHP开发 阅读(115)

之前我已经使用Elasticsearch作为自己站内搜索的驱动,但是ES的体量过大对于一些低配置的服务器来说,使用起来比较吃力。有一天看到一个群里的朋友推荐了ZincSearch。ZincSearch作为一款Elasticsearch 的轻量级替代品,我觉得对于许多小站长来说肯定非常实用。经过一段时间的研究,终于将ZincSearch纳入了laravel开发框架里面了。下面我将详细讲解我们的操作。

zincsearch-3.jpg

一、在您的服务器上安装ZincSearch

1、我的服务器是宝塔面板管理的,我需要先安装Docker。点击右侧Docker按钮,然后弹窗根据指引安装即可,过程非常简单,不再赘述。

6.png

2、在Docker中安装ZincSearch。

在宝塔面板的终端或 Docker 控制台中执行命令:

docker pull zincsearch/zinc:latest

启动 ZincSearch 容器

  • 运行下面的命令启动 ZincSearch 容器,并将容器的 4080 端口映射到主机同一端口:
  • docker run -d -p 4080:4080 zincsearch/zinc:latest
  • 访问 ZincSearch 打开浏览器,输入 http://你的服务器IP:4080,即可访问 ZincSearch 的 Web 管理界面。
  • 按照以上步骤,你就可以在宝塔面板中成功安装并启动 ZincSearch 了。
    7.png

    二、在您的laravel网站上使用ZincSearch

    1、laravel框架中需要安装 GuzzleHTTP

    composer require guzzlehttp/guzzle

    2、Laravel 配置,添加 Zinc 配置到 .env

    ZINC_HOST=http://localhost:4080
    ZINC_USER=admin
    ZINC_PASSWORD=admin
    ZINC_INDEX=posts

    3、创建 Zinc 服务类

    // app/Services/ZincSearchService.php
    
    namespace App\Services;
    
    use GuzzleHttp\Client;
    use GuzzleHttp\Exception\GuzzleException;
    
    class ZincSearchService
    {
        protected Client $client;
    
        public function __construct()
        {
            $this->client = new Client([
                'base_uri' => env('ZINC_HOST'),
                'auth' => [env('ZINC_USER'), env('ZINC_PASSWORD')],
                'headers' => ['Content-Type' => 'application/json']
            ]);
        }
    
        // 创建索引
        public function createIndex(): void
        {
            try {
                $this->client->put("/api/index/{$this->getIndexName()}", [
                    'json' => [
                        'name' => $this->getIndexName(),
                        'storage_type' => 'disk',
                        'mappings' => [
                            'properties' => [
                                'title' => ['type' => 'text'],
                                'content' => ['type' => 'text']
                            ]
                        ]
                    ]
                ]);
            } catch (GuzzleException $e) {
                // 处理异常
            }
        }
    
        // 索引文档
        public function indexDocument(string $id, array $document): void
        {
            $this->client->put("/api/{$this->getIndexName()}/_doc/{$id}", [
                'json' => $document
            ]);
        }
    
         // 搜索文档
        public function search(string $query, int $from = 0, int $num =20): array
        {
             
            try {
                $response = $this->client->post("/api/{$this->getIndexName()}/_search", [
      
              'json' => [
                  "search_type" => "match", 
                  'query'       => [
                   'term' => $query
                  ],
                   'from'        => $from,
                   'max_results' => $num,
                 
                    ]
                    
              ]);
    
                return json_decode($response->getBody(), true);
            } catch (GuzzleException $e) {
                return [];
            }
        }
        // 更新文档
        public function updateDocument(string $id, array $document): void
        {
            $this->client->put("/api/{$this->getIndexName()}/_doc/{$id}", [
                'json' => $document
            ]);
        }
    
        // 删除文档
        public function deleteDocument(string $id): void
        {
            $this->client->delete("/api/{$this->getIndexName()}/_doc/{$id}");
        }
    
        private function getIndexName(): string
        {
            return env('ZINC_INDEX', 'default_index');
        }
    }

    4、模型集成

    // app/Models/Post.php
    
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Post extends Model
    {
        protected $fillable = ['title', 'content'];
    
        protected static function booted()
        {
            static::created(function ($post) {
                app(ZincSearchService::class)->indexDocument([
                    'id' => $post->id,
                    'title' => $post->title,
                    'content' => $post->content
                ]);
            });
    
            static::updated(function ($post) {
                app(ZincSearchService::class)->updateDocument($post->id, [
                    'title' => $post->title,
                    'content' => $post->content
                ]);
            });
    
            static::deleted(function ($post) {
                app(ZincSearchService::class)->deleteDocument($post->id);
            });
        }
    }

    5、批量导入模型制作

     public function createArticleAll(Request $request)
        {
            $a=Article::chunk(200, function ($posts) {
                foreach ($posts as $post) {
                    app(ZincSearchService::class)->indexDocument($post->id,[
                        'id' => $post->id,
                        'time' => $post->updated_at->format('Y-m-d H:i:s'),
                        'image' => $post->image,
                        'intro' => $post->intro,
                        'title' => $post->title,
                        'details' => $post->details,
                    ]);
                }
            });
            return $a;
        }

    6、搜索模型

     $service = new ZincSearchService();
      $data=[
                'user'=>1,
                'posts'=>$service->search($request->k,0,15),
                'keyword'=>$request->k,
               
            ];
           
    
          return view('search',compact('data'));

    7、路由配置

    // routes/web.php
    
    Route::get('/search', [SearchController::class, 'search']);
    
    
    Route::get('/createArticleAll', [SearchController::class, 'createArticleAll']);

    通过以上步骤,laravel可以使用搜索了。速度还不错,可以使用本站搜索进行体验哦。

    转载请注明: BoxPHP » 如何在 Laravel 中用 ZincSearch 实现站内搜索引擎
    上一篇 未来50年,人类和AI必有一战
    下一篇 跟着夫唯老师学习跨境电商的一些感想

    与本文相关的文章