Completed
Pull Request — master (#563)
by Mantas
05:57 queued 17s
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.4285
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
 * Document 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->className = $className;
61
        $this->type = $this->resolveType($className);
62
    }
63
64
    /**
65
     * Returns elasticsearch manager used in the repository.
66
     *
67
     * @return Manager
68
     */
69
    public function getManager()
70
    {
71
        return $this->manager;
72
    }
73
74
    /**
75
     * @return array
76
     */
77
    public function getType()
78
    {
79
        return $this->type;
80
    }
81
82
    /**
83
     * Returns a single document data by ID or null if document is not found.
84
     *
85
     * @param string $id Document ID to find
86
     *
87
     * @return object
88
     */
89
    public function find($id)
90
    {
91
        return $this->manager->find($this->type, $id);
92
    }
93
94
    /**
95
     * Finds documents by a set of criteria.
96
     *
97
     * @param array      $criteria   Example: ['group' => ['best', 'worst'], 'job' => 'medic'].
98
     * @param array|null $orderBy    Example: ['name' => 'ASC', 'surname' => 'DESC'].
99
     * @param int|null   $limit      Example: 5.
100
     * @param int|null   $offset     Example: 30.
101
     *
102
     * @return array|DocumentIterator The objects.
103
     */
104
    public function findBy(
105
        array $criteria,
106
        array $orderBy = [],
107
        $limit = null,
108
        $offset = null
109
    ) {
110
        $search = $this->createSearch();
111
112
        if ($limit !== null) {
113
            $search->setSize($limit);
114
        }
115
        if ($offset !== null) {
116
            $search->setFrom($offset);
117
        }
118
119
        foreach ($criteria as $field => $value) {
120
            $search->addQuery(
121
                new QueryStringQuery(is_array($value) ? implode(' OR ', $value) : $value, ['default_field' => $field])
122
            );
123
        }
124
125
        foreach ($orderBy as $field => $direction) {
126
            $search->addSort(new FieldSort($field, $direction));
127
        }
128
129
        return $this->execute($search);
130
    }
131
132
    /**
133
     * Finds a single document by a set of criteria.
134
     *
135
     * @param array      $criteria   Example: ['group' => ['best', 'worst'], 'job' => 'medic'].
136
     * @param array|null $orderBy    Example: ['name' => 'ASC', 'surname' => 'DESC'].
137
     *
138
     * @return object|null The object.
139
     */
140
    public function findOneBy(array $criteria, array $orderBy = [])
141
    {
142
        $result = $this->findBy($criteria, $orderBy, null, null);
143
144
        return $result->first();
145
    }
146
147
    /**
148
     * Returns search instance.
149
     *
150
     * @return Search
151
     */
152
    public function createSearch()
153
    {
154
        return new Search();
155
    }
156
157
    /**
158
     * Executes given search.
159
     *
160
     * @param Search $search
161
     * @param string $resultsType
162
     *
163
     * @return DocumentIterator|RawIterator|array
164
     *
165
     * @throws \Exception
166
     */
167
    public function execute(Search $search, $resultsType = Result::RESULTS_OBJECT)
168
    {
169
        return $this->manager->execute([$this->type], $search, $resultsType);
170
    }
171
172
    /**
173
     * Counts documents by given search.
174
     *
175
     * @param Search $search
176
     * @param array  $params
177
     * @param bool   $returnRaw If set true returns raw response gotten from client.
178
     *
179
     * @return int|array
180
     */
181
    public function count(Search $search, array $params = [], $returnRaw = false)
182
    {
183
        $body = array_merge(
184
            [
185
                'index' => $this->getManager()->getIndexName(),
186
                'type' => $this->type,
187
                'body' => $search->toArray(),
188
            ],
189
            $params
190
        );
191
192
        $results = $this
193
            ->getManager()
194
            ->getClient()->count($body);
195
196
        if ($returnRaw) {
197
            return $results;
198
        } else {
199
            return $results['count'];
200
        }
201
    }
202
203
    /**
204
     * Removes a single document data by ID.
205
     *
206
     * @param string $id Document ID to remove.
207
     *
208
     * @return array
209
     *
210
     * @throws \LogicException
211
     */
212
    public function remove($id)
213
    {
214
        $params = [
215
            'index' => $this->getManager()->getIndexName(),
216
            'type' => $this->type,
217
            'id' => $id,
218
        ];
219
220
        $response = $this->getManager()->getClient()->delete($params);
221
222
        return $response;
223
    }
224
225
    /**
226
     * Partial document update.
227
     *
228
     * @param string $id     Document id to update.
229
     * @param array  $fields Fields array to update.
230
     * @param string $script Groovy script to update fields.
231
     * @param array  $params Additional parameters to pass to the client.
232
     *
233
     * @return array
234
     */
235
    public function update($id, array $fields = [], $script = null, array $params = [])
236
    {
237
        $body = array_filter(
238
            [
239
                'doc' => $fields,
240
                'script' => $script,
241
            ]
242
        );
243
244
        $params = array_merge(
245
            [
246
                'id' => $id,
247
                'index' => $this->getManager()->getIndexName(),
248
                'type' => $this->type,
249
                'body' => $body,
250
            ],
251
            $params
252
        );
253
254
        return $this->getManager()->getClient()->update($params);
255
    }
256
257
    /**
258
     * Resolves elasticsearch type by class name.
259
     *
260
     * @param string $className
261
     *
262
     * @return array
263
     */
264
    private function resolveType($className)
265
    {
266
        return $this->getManager()->getMetadataCollector()->getDocumentType($className);
267
    }
268
269
    /**
270
     * Returns fully qualified class name.
271
     *
272
     * @return string
273
     */
274
    public function getClassName()
275
    {
276
        return $this->className;
277
    }
278
}
279