laravel 自定义Elasticsearch引擎 Scout

自定义引擎

如果内置的 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"


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值