laravel 自定义Elasticsearch引擎 Scout

xiaoxiao2021-02-28  12

自定义引擎

如果内置的 Scout 搜索引擎不能满足你的需求,你可以写自定义的引擎并且将它注册到 Scout。你的引擎需要继承  Laravel\Scout\Engines\Engine  抽象类,这个抽象类包含了你自定义的引擎必须要实现的五种方法 use Laravel\Scout\Builder; abstract public function update($models); abstract public function delete($models); abstract public function search(Builder $builder); abstract public function paginate(Builder $builder, $perPage, $page); abstract public function map($results, $model) <?php namespace App\Engine; use Laravel\Scout\Builder; use Laravel\Scout\Engines\Engine; use Elasticsearch\Client; use Illuminate\Database\Eloquent\Collection; class ElasticsearchEngine extends Engine{ //索引 protected $index; //搜索引擎 protected $elastic; //初始化 public function __construct(Client $elastic,$index) { $this->elastic=$elastic; $this->index=$index; } //更新 public function update($models) { $params['body'] = []; $models->each(function($model) use (&$params) { $params['body'][] = [ 'update' => [ '_id' => $model->getKey(), '_index' => $this->index, '_type' => $model->searchableAs(), ] ]; $params['body'][] = [ 'doc' => $model->toSearchableArray(), 'doc_as_upsert' => true ]; }); $this->elastic->bulk($params); } //删除 public function delete($models) { $params['body'] = []; $models->each(function($model) use (&$params) { $params['body'][] = [ 'delete' => [ '_id' => $model->getKey(), '_index' =>$this->index, '_type' => $model->searchableAs(), ] ]; }); $this->elastic->bulk($params); } //搜索 public function search(Builder $builder) { return $this->performSearch($builder, array_filter([ 'numericFilters' => $this->filters($builder), 'size' => $builder->limit, ])); } //搜索参数 protected function performSearch(Builder $builder, array $options = []) { $params = [ 'index' => $this->index, 'type' => $builder->index ?: $builder->model->searchableAs(), 'body' => [ 'query' => [ 'bool' => [ 'must' => [['query_string' => [ 'query' => "*{$builder->query}*"]]] ] ] ] ]; if ($sort = $this->sort($builder)) { $params['body']['sort'] = $sort; } if (isset($options['from'])) { $params['body']['from'] = $options['from']; } if (isset($options['size'])) { $params['body']['size'] = $options['size']; } if (isset($options['numericFilters']) && count($options['numericFilters'])) { $params['body']['query']['bool']['must'] = array_merge($params['body']['query']['bool']['must'], $options['numericFilters']); } if ($builder->callback) { return call_user_func( $builder->callback, $this->elastic, $builder->query, $params ); } return $this->elastic->search($params); } //获取查询的过滤器数组 protected function filters(Builder $builder) { return collect($builder->wheres)->map(function ($value, $key) { if (is_array($value)) { return ['terms' => [$key => $value]]; } return ['match_phrase' => [$key => $value]]; })->values()->all(); } //生成排序结果 protected function sort($builder) { if (count($builder->orders) == 0) { return null; } return collect($builder->orders)->map(function($order) { return [$order['column'] => $order['direction']]; })->toArray(); } //分页 public function paginate(Builder $builder, $perPage, $page) { $result = $this->performSearch($builder, [ 'numericFilters' => $this->filters($builder), 'from' => (($page * $perPage) - $perPage), 'size' => $perPage, ]); $result['nbPages'] = $result['hits']['total']/$perPage; return $result; } //采集并返回给定结果的主键 public function mapIds($results) { return collect($results['hits']['hits'])->pluck('_id')->values(); } //将给定结果映射到给定模式的实例 public function map($results, $model) { if ($results['hits']['total'] === 0) { return Collection::make(); } $keys = collect($results['hits']['hits']) ->pluck('_id')->values()->all(); $models = $model->whereIn( $model->getKeyName(), $keys )->get()->keyBy($model->getKeyName()); return collect($results['hits']['hits'])->map(function ($hit) use ($model, $models) { return isset($models[$hit['_id']]) ? $models[$hit['_id']] : null; })->filter()->values(); } //获取总行数 public function getTotalCount($results) { return $results['hits']['total']; } }

注册引擎

你只需要从  AppServiceProvider  下的  boot  方法或者应用中使用的任何一个服务提供器调用  extend  方法

public function boot() { $this->bootElasticsearch(); } protected function bootElasticsearch() { resolve(EngineManager::class)->extend('elasticsearch', function () { $config = config('scout.elasticsearch'); $client = ClientBuilder::create() ->setHosts($config['hosts']) ->build(); return new ElasticsearchEngine($client); }); } 引擎注册后,你可以在  config/scout.php  配置文件中指定它为默认的 Scout  driver 'driver' => env('SCOUT_DRIVER', 'elasticsearch'), 'elasticsearch' => [ 'index' => env('ELASTICSEARCH_INDEX', 'mall'), 'hosts' => [ env('ELASTICSEARCH_HOST', 'http://elasticsearch:9200'), ], ],

提示:先安装:https://github.com/elastic/elasticsearch-php

"elasticsearch/elasticsearch": "~6.0"

转载请注明原文地址: https://www.6miu.com/read-2450184.html

最新回复(0)