Completed
Push — master ( c40a22...4c05c5 )
by Hamoud
23:40 queued 09:50
created

ScoutElasticEngine::update()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

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