Completed
Pull Request — master (#514)
by Mantas
02:41
created

Repository::findOneBy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 6
rs 9.4286
cc 1
eloc 3
nc 1
nop 2
1
<?php
2
3
/*
4
 * This file is part of the ONGR package.
5
 *
6
 * (c) NFQ Technologies UAB <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace ONGR\ElasticsearchBundle\Service;
13
14
use ONGR\ElasticsearchBundle\Result\RawIterator;
15
use ONGR\ElasticsearchBundle\Result\Result;
16
use ONGR\ElasticsearchDSL\Query\QueryStringQuery;
17
use ONGR\ElasticsearchDSL\Search;
18
use ONGR\ElasticsearchDSL\Sort\FieldSort;
19
use ONGR\ElasticsearchBundle\Result\DocumentIterator;
20
21
/**
22
 * Repository class.
23
 */
24
class Repository
25
{
26
    /**
27
     * @var Manager
28
     */
29
    private $manager;
30
31
    /**
32
     * @var string Fully qualified class name
33
     */
34
    private $className;
35
36
    /**
37
     * @var string Elasticsearch type name
38
     */
39
    private $type;
40
41
    /**
42
     * Constructor.
43
     *
44
     * @param Manager $manager
45
     * @param string  $className
46
     */
47
    public function __construct($manager, $className)
48
    {
49
        if (!is_string($className)) {
50
            throw new \InvalidArgumentException('Class name must be a string.');
51
        }
52
53
        if (!class_exists($className)) {
54
            throw new \InvalidArgumentException(
55
                sprintf('Cannot create repository for non-existing class "%s".', $className)
56
            );
57
        }
58
59
        $this->manager = $manager;
60
        $this->type = $this->resolveType($className);
61
    }
62
63
    /**
64
     * Returns elasticsearch manager used in the repository.
65
     *
66
     * @return Manager
67
     */
68
    public function getManager()
69
    {
70
        return $this->manager;
71
    }
72
73
    /**
74
     * @return array
75
     */
76
    public function getType()
77
    {
78
        return $this->type;
79
    }
80
81
    /**
82
     * Returns a single document data by ID or null if document is not found.
83
     *
84
     * @param string $id Document ID to find
85
     *
86
     * @return object
87
     */
88
    public function find($id)
89
    {
90
        return $this->manager->find($this->type, $id);
91
    }
92
93
    /**
94
     * Finds documents by a set of criteria.
95
     *
96
     * @param array      $criteria   Example: ['group' => ['best', 'worst'], 'job' => 'medic'].
97
     * @param array|null $orderBy    Example: ['name' => 'ASC', 'surname' => 'DESC'].
98
     * @param int|null   $limit      Example: 5.
99
     * @param int|null   $offset     Example: 30.
100
     *
101
     * @return array|DocumentIterator The objects.
102
     */
103
    public function findBy(
104
        array $criteria,
105
        array $orderBy = [],
106
        $limit = null,
107
        $offset = null
108
    ) {
109
        $search = $this->createSearch();
110
111
        if ($limit !== null) {
112
            $search->setSize($limit);
113
        }
114
        if ($offset !== null) {
115
            $search->setFrom($offset);
116
        }
117
118
        foreach ($criteria as $field => $value) {
119
            $search->addQuery(
120
                new QueryStringQuery(is_array($value) ? implode(' OR ', $value) : $value, ['default_field' => $field])
121
            );
122
        }
123
124
        foreach ($orderBy as $field => $direction) {
125
            $search->addSort(new FieldSort($field, $direction));
126
        }
127
128
        return $this->execute($search);
129
    }
130
131
    /**
132
     * Finds a single document by a set of criteria.
133
     *
134
     * @param array      $criteria   Example: ['group' => ['best', 'worst'], 'job' => 'medic'].
135
     * @param array|null $orderBy    Example: ['name' => 'ASC', 'surname' => 'DESC'].
136
     *
137
     * @return object|null The object.
138
     */
139
    public function findOneBy(array $criteria, array $orderBy = [])
140
    {
141
        $result = $this->findBy($criteria, $orderBy, null, null);
142
143
        return $result->first();
144
    }
145
146
    /**
147
     * Returns search instance.
148
     *
149
     * @return Search
150
     */
151
    public function createSearch()
152
    {
153
        return new Search();
154
    }
155
156
    /**
157
     * Executes given search.
158
     *
159
     * @param Search $search
160
     * @param string $resultsType
161
     *
162
     * @return DocumentIterator|RawIterator|array
163
     *
164
     * @throws \Exception
165
     */
166
    public function execute(Search $search, $resultsType = Result::RESULTS_OBJECT)
167
    {
168
        return $this->manager->execute([$this->type], $search, $resultsType);
169
    }
170
171
    /**
172
     * Counts documents by given search.
173
     *
174
     * @param Search $search
175
     * @param array  $params
176
     * @param bool   $returnRaw If set true returns raw response gotten from client.
177
     *
178
     * @return int|array
179
     */
180
    public function count(Search $search, array $params = [], $returnRaw = false)
181
    {
182
        $body = array_merge(
183
            [
184
                'index' => $this->getManager()->getIndexName(),
185
                'type' => $this->type,
186
                'body' => $search->toArray(),
187
            ],
188
            $params
189
        );
190
191
        $results = $this
192
            ->getManager()
193
            ->getClient()->count($body);
194
195
        if ($returnRaw) {
196
            return $results;
197
        } else {
198
            return $results['count'];
199
        }
200
    }
201
202
    /**
203
     * Delete by query.
204
     *
205
     * @param Search $search
206
     *
207
     * @return array
208
     */
209
    public function deleteByQuery(Search $search)
210
    {
211
        $params = [
212
            'index' => $this->getManager()->getIndexName(),
213
            'type' => $this->type,
214
            'body' => $search->toArray(),
215
        ];
216
217
        return $this
218
            ->getManager()
219
            ->getClient()
220
            ->deleteByQuery($params);
221
    }
222
223
    /**
224
     * Removes a single document data by ID.
225
     *
226
     * @param string $id Document ID to remove.
227
     *
228
     * @return array
229
     *
230
     * @throws \LogicException
231
     */
232
    public function remove($id)
233
    {
234
        $params = [
235
            'index' => $this->getManager()->getIndexName(),
236
            'type' => $this->type,
237
            'id' => $id,
238
        ];
239
240
        $response = $this->getManager()->getClient()->delete($params);
241
242
        return $response;
243
    }
244
245
    /**
246
     * Partial document update.
247
     *
248
     * @param string $id     Document id to update.
249
     * @param array  $fields Fields array to update.
250
     * @param string $script Groovy script to update fields.
251
     * @param array  $params Additional parameters to pass to the client.
252
     *
253
     * @return array
254
     */
255
    public function update($id, array $fields = [], $script = null, array $params = [])
256
    {
257
        $body = array_filter(
258
            [
259
                'doc' => $fields,
260
                'script' => $script,
261
            ]
262
        );
263
264
        $params = array_merge(
265
            [
266
                'id' => $id,
267
                'index' => $this->getManager()->getIndexName(),
268
                'type' => $this->type,
269
                'body' => $body,
270
            ],
271
            $params
272
        );
273
274
        return $this->getManager()->getClient()->update($params);
275
    }
276
277
    /**
278
     * Resolves elasticsearch type by class name.
279
     *
280
     * @param string $className
281
     *
282
     * @return array
283
     */
284
    private function resolveType($className)
285
    {
286
        return $this->getManager()->getMetadataCollector()->getDocumentType($className);
287
    }
288
289
    /**
290
     * Returns fully qualified class name.
291
     *
292
     * @return string
293
     */
294
    public function getClassName()
295
    {
296
        return $this->className;
297
    }
298
}
299