Completed
Pull Request — master (#3)
by Hamoud
28:19 queued 27:02
created

ScoutElasticEngine::paginate()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 28
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 28
ccs 13
cts 13
cp 1
rs 8.8571
cc 2
eloc 17
nc 2
nop 3
crap 2
1
<?php
2
3
namespace Alhoqbani\Elastic;
4
5
use Elasticsearch\Client;
6
use Illuminate\Database\Eloquent\Collection;
7
use Laravel\Scout\Builder;
8
use Laravel\Scout\Engines\Engine;
9
10
class ScoutElasticEngine extends Engine
11
{
12
13
    /**
14
     * The Elasticsearch client.
15
     *
16
     * @var \Elasticsearch\Client
17
     */
18
    private $client;
19
20
    /**
21
     * ElasticSearchScoutEngine constructor.
22
     *
23
     * @param \Elasticsearch\Client $client
24
     */
25 33
    public function __construct(Client $client)
26
    {
27 33
        $this->client = $client;
28 33
    }
29
30
    /**
31
     * Update the given model in the index.
32
     *
33
     * @param  \Illuminate\Database\Eloquent\Collection $models
34
     *
35
     * @return void
36
     */
37 3
    public function update($models)
38
    {
39 3
        $index = $models->first()->searchableAs();
40
41 3
        $params = ['body' => []];
42 3
        foreach ($models as $model) {
43 3
            $array = $model->toSearchableArray();
44
45 3
            if (empty($array)) {
46
                return;
47
            }
48
49 3
            $params['body'][] = [
50
                'index' => [
51 3
                    '_index' => $index,
52 3
                    '_type'  => $index,
53 3
                    '_id'    => $model->getKey(),
54
                ],
55
            ];
56 3
            $params['body'][] = $array;
57
        }
58
59 3
        $this->client->bulk($params);
60 3
    }
61
62
    /**
63
     * Remove the given model from the index.
64
     *
65
     * @param  \Illuminate\Database\Eloquent\Collection $models
66
     *
67
     * @return void
68
     */
69 3
    public function delete($models)
70
    {
71 3
        $index = $models->first()->searchableAs();
72
73 3
        $params = ['body' => []];
74 3
        foreach ($models as $model) {
75 3
            $params['body'][] = [
76
                'delete' => [
77 3
                    '_index' => $index,
78 3
                    '_type'  => $index,
79 3
                    '_id'    => $model->getKey(),
80
                ],
81
            ];
82
        }
83
84 3
        $this->client->bulk($params);
85 3
    }
86
87
    /**
88
     * Perform the given search on the engine.
89
     *
90
     * @param  \Laravel\Scout\Builder $builder
91
     *
92
     * @return mixed
93
     */
94 12
    public function search(Builder $builder)
95
    {
96
        $params = [
97 12
            'index' => $builder->index ?? $builder->model->searchableAs(),
98 12
            'type'  => $builder->index ?? $builder->model->searchableAs(),
99
            'body'  => [
100 12
                'size'  => $builder->limit ?? $builder->model->getPerPage(),
101
                'query' => [
102
                    'multi_match' => [
103 12
                        'query'  => $builder->query,
104 12
                        'fields' => '_all',
105
                    ],
106
                ],
107
            ],
108
        ];
109
110 12
        if ($builder->callback) {
111 3
            $params =  call_user_func(
112 3
                $builder->callback,
113 3
                $this->client,
114 3
                $builder->query
115
            );
116
        }
117
118 12
        return $this->client->search($params);
119
    }
120
121
    /**
122
     * Perform the given search on the engine.
123
     *
124
     * @param  \Laravel\Scout\Builder $builder
125
     * @param  int                    $perPage
126
     * @param  int                    $page
127
     *
128
     * @return mixed
129
     */
130 12
    public function paginate(Builder $builder, $perPage, $page)
131
    {
132
        $params = [
133 12
            'index' => $builder->index ?? $builder->model->searchableAs(),
134 12
            'type'  => $builder->index ?? $builder->model->searchableAs(),
135
            'body'  => [
136
                'query' => [
137
                    'multi_match' => [
138 12
                        'query'  => $builder->query,
139 12
                        'fields' => '_all',
140
                    ],
141
                ],
142
            ],
143
        ];
144
145 12
        if ($builder->callback) {
146 3
            $params =  call_user_func(
147 3
                $builder->callback,
148 3
                $this->client,
149 3
                $builder->query
150
            );
151
        }
152
153 12
        $params['body']['size'] = $perPage;
154 12
        $params['body']['from'] = ($page - 1) * $perPage;
155
156 12
        return $this->client->search($params);
157
    }
158
159
    /**
160
     * Pluck and return the primary keys of the given results.
161
     *
162
     * @param  mixed $results
163
     *
164
     * @return \Illuminate\Support\Collection
165
     */
166
    public function mapIds($results)
167
    {
168
        return collect($results['hits']['hits'])->pluck('_id')->values();
169
    }
170
171
    /**
172
     * Map the given results to instances of the given model.
173
     *
174
     * @param  mixed                               $results
175
     * @param  \Illuminate\Database\Eloquent\Model $model
176
     *
177
     * @return \Illuminate\Database\Eloquent\Collection
178
     */
179 3
    public function map($results, $model)
180
    {
181 3
        if ($results['hits']['total'] === 0) {
182
            return Collection::make();
183
        }
184
185 3
        $keys = collect($results['hits']['hits'])
186 3
            ->pluck('_id')->values()->all();
187
188 3
        $models = $model->whereIn(
189 3
            $model->getQualifiedKeyName(),
190 3
            $keys
191 3
        )->get()->keyBy($model->getKeyName());
192
193 3
        return Collection::make($results['hits']['hits'])->map(function ($hit) use ($model, $models) {
194 3
            $key = $hit['_id'];
195
196 3
            if (isset($models[$key])) {
197 3
                return $models[$key];
198
            }
199 3
        })->filter()->values();
200
    }
201
202
    /**
203
     * Get the total count from a raw result returned by the engine.
204
     *
205
     * @param  mixed $results
206
     *
207
     * @return int
208
     */
209
    public function getTotalCount($results)
210
    {
211
        return $results['hits']['total'];
212
    }
213
}
214