3 namespace Drupal\KernelTests\Core\Entity;
5 use Drupal\field\Entity\FieldConfig;
6 use Drupal\field\Entity\FieldStorageConfig;
9 * Tests the Entity Query Aggregation API.
12 * @see \Drupal\entity_test\Entity\EntityTest
14 class EntityQueryAggregateTest extends EntityKernelTestBase {
21 public static $modules = [];
24 * The entity_test storage to create the test entities.
26 * @var \Drupal\entity_test\EntityTestStorage
28 protected $entityStorage;
31 * The actual query result, to compare later.
35 protected $queryResult;
38 * The query factory to create entity queries.
40 * @var \Drupal\Core\Entity\Query\QueryFactory
44 protected function setUp() {
47 $this->entityStorage = $this->entityManager->getStorage('entity_test');
48 $this->factory = $this->container->get('entity.query');
50 // Add some fieldapi fields to be used in the test.
51 for ($i = 1; $i <= 2; $i++) {
52 $field_name = 'field_test_' . $i;
53 FieldStorageConfig::create([
54 'field_name' => $field_name,
55 'entity_type' => 'entity_test',
60 'field_name' => $field_name,
61 'entity_type' => 'entity_test',
62 'bundle' => 'entity_test',
66 $entity = $this->entityStorage->create([
72 $entity->enforceIsNew();
75 $entity = $this->entityStorage->create([
81 $entity->enforceIsNew();
83 $entity = $this->entityStorage->create([
89 $entity->enforceIsNew();
91 $entity = $this->entityStorage->create([
97 $entity->enforceIsNew();
99 $entity = $this->entityStorage->create([
105 $entity->enforceIsNew();
107 $entity = $this->entityStorage->create([
113 $entity->enforceIsNew();
119 * Test aggregation support.
121 public function testAggregation() {
122 // Apply a simple groupby.
123 $this->queryResult = $this->factory->getAggregate('entity_test')
127 $this->assertResults([
133 $function_expected = [];
134 $function_expected['count'] = [['id_count' => 6]];
135 $function_expected['min'] = [['id_min' => 1]];
136 $function_expected['max'] = [['id_max' => 6]];
137 $function_expected['sum'] = [['id_sum' => 21]];
138 $function_expected['avg'] = [['id_avg' => (21.0 / 6.0)]];
140 // Apply a simple aggregation for different aggregation functions.
141 foreach ($function_expected as $aggregation_function => $expected) {
142 $this->queryResult = $this->factory->getAggregate('entity_test')
143 ->aggregate('id', $aggregation_function)
145 $this->assertEqual($this->queryResult, $expected);
148 // Apply aggregation and groupby on the same query.
149 $this->queryResult = $this->factory->getAggregate('entity_test')
150 ->aggregate('id', 'COUNT')
153 $this->assertResults([
154 ['user_id' => 1, 'id_count' => 1],
155 ['user_id' => 2, 'id_count' => 3],
156 ['user_id' => 3, 'id_count' => 2],
159 // Apply aggregation and a condition which matches.
160 $this->queryResult = $this->factory->getAggregate('entity_test')
161 ->aggregate('id', 'COUNT')
163 ->conditionAggregate('id', 'COUNT', 8)
165 $this->assertResults([]);
167 // Don't call aggregate to test the implicit aggregate call.
168 $this->queryResult = $this->factory->getAggregate('entity_test')
170 ->conditionAggregate('id', 'COUNT', 8)
172 $this->assertResults([]);
174 // Apply aggregation and a condition which matches.
175 $this->queryResult = $this->factory->getAggregate('entity_test')
176 ->aggregate('id', 'count')
178 ->conditionAggregate('id', 'COUNT', 6)
180 $this->assertResults([['id_count' => 6]]);
182 // Apply aggregation, a groupby and a condition which matches partially via
184 $this->queryResult = $this->factory->getAggregate('entity_test')
185 ->aggregate('id', 'count')
186 ->conditionAggregate('id', 'count', 2)
189 $this->assertResults([['id_count' => 2, 'user_id' => 3]]);
191 // Apply aggregation, a groupby and a condition which matches partially via
193 $this->queryResult = $this->factory->getAggregate('entity_test')
194 ->aggregate('id', 'count')
195 ->conditionAggregate('id', 'COUNT', 1, '>')
198 $this->assertResults([
199 ['id_count' => 2, 'user_id' => 3],
200 ['id_count' => 3, 'user_id' => 2],
203 // Apply aggregation and a sort. This might not be useful, but have a proper
205 $this->queryResult = $this->factory->getAggregate('entity_test')
206 ->aggregate('id', 'COUNT')
207 ->sortAggregate('id', 'COUNT')
209 $this->assertSortedResults([['id_count' => 6]]);
211 // Don't call aggregate to test the implicit aggregate call.
212 $this->queryResult = $this->factory->getAggregate('entity_test')
213 ->sortAggregate('id', 'COUNT')
215 $this->assertSortedResults([['id_count' => 6]]);
217 // Apply aggregation, groupby and a sort descending.
218 $this->queryResult = $this->factory->getAggregate('entity_test')
219 ->aggregate('id', 'COUNT')
221 ->sortAggregate('id', 'COUNT', 'DESC')
223 $this->assertSortedResults([
224 ['user_id' => 2, 'id_count' => 3],
225 ['user_id' => 3, 'id_count' => 2],
226 ['user_id' => 1, 'id_count' => 1],
229 // Apply aggregation, groupby and a sort ascending.
230 $this->queryResult = $this->factory->getAggregate('entity_test')
231 ->aggregate('id', 'COUNT')
233 ->sortAggregate('id', 'COUNT', 'ASC')
235 $this->assertSortedResults([
236 ['user_id' => 1, 'id_count' => 1],
237 ['user_id' => 3, 'id_count' => 2],
238 ['user_id' => 2, 'id_count' => 3],
241 // Apply aggregation, groupby, an aggregation condition and a sort with the
243 $this->queryResult = $this->factory->getAggregate('entity_test')
244 ->aggregate('id', 'COUNT')
246 ->sortAggregate('id', 'COUNT')
247 ->conditionAggregate('id', 'COUNT', 2)
249 $this->assertSortedResults([['id_count' => 2, 'user_id' => 3]]);
251 // Apply aggregation, groupby, an aggregation condition and a sort with the
252 // operator '<' and order ASC.
253 $this->queryResult = $this->factory->getAggregate('entity_test')
254 ->aggregate('id', 'COUNT')
256 ->sortAggregate('id', 'COUNT', 'ASC')
257 ->conditionAggregate('id', 'COUNT', 3, '<')
259 $this->assertSortedResults([
260 ['id_count' => 1, 'user_id' => 1],
261 ['id_count' => 2, 'user_id' => 3],
264 // Apply aggregation, groupby, an aggregation condition and a sort with the
265 // operator '<' and order DESC.
266 $this->queryResult = $this->factory->getAggregate('entity_test')
267 ->aggregate('id', 'COUNT')
269 ->sortAggregate('id', 'COUNT', 'DESC')
270 ->conditionAggregate('id', 'COUNT', 3, '<')
272 $this->assertSortedResults([
273 ['id_count' => 2, 'user_id' => 3],
274 ['id_count' => 1, 'user_id' => 1],
277 // Test aggregation/groupby support for fieldapi fields.
279 // Just group by a fieldapi field.
280 $this->queryResult = $this->factory->getAggregate('entity_test')
281 ->groupBy('field_test_1')
283 $this->assertResults([
284 ['field_test_1' => 1],
285 ['field_test_1' => 2],
286 ['field_test_1' => 3],
289 // Group by a fieldapi field and aggregate a normal property.
290 $this->queryResult = $this->factory->getAggregate('entity_test')
291 ->aggregate('user_id', 'COUNT')
292 ->groupBy('field_test_1')
295 $this->assertResults([
296 ['field_test_1' => 1, 'user_id_count' => 2],
297 ['field_test_1' => 2, 'user_id_count' => 3],
298 ['field_test_1' => 3, 'user_id_count' => 1],
301 // Group by a normal property and aggregate a fieldapi field.
302 $this->queryResult = $this->factory->getAggregate('entity_test')
303 ->aggregate('field_test_1', 'COUNT')
307 $this->assertResults([
308 ['user_id' => 1, 'field_test_1_count' => 1],
309 ['user_id' => 2, 'field_test_1_count' => 3],
310 ['user_id' => 3, 'field_test_1_count' => 2],
313 $this->queryResult = $this->factory->getAggregate('entity_test')
314 ->aggregate('field_test_1', 'SUM')
317 $this->assertResults([
318 ['user_id' => 1, 'field_test_1_sum' => 1],
319 ['user_id' => 2, 'field_test_1_sum' => 5],
320 ['user_id' => 3, 'field_test_1_sum' => 5],
323 // Aggregate by two different fieldapi fields.
324 $this->queryResult = $this->factory->getAggregate('entity_test')
325 ->aggregate('field_test_1', 'SUM')
326 ->aggregate('field_test_2', 'SUM')
329 $this->assertResults([
330 ['user_id' => 1, 'field_test_1_sum' => 1, 'field_test_2_sum' => 2],
331 ['user_id' => 2, 'field_test_1_sum' => 5, 'field_test_2_sum' => 16],
332 ['user_id' => 3, 'field_test_1_sum' => 5, 'field_test_2_sum' => 10],
335 // This time aggregate the same field twice.
336 $this->queryResult = $this->factory->getAggregate('entity_test')
337 ->aggregate('field_test_1', 'SUM')
338 ->aggregate('field_test_1', 'COUNT')
341 $this->assertResults([
342 ['user_id' => 1, 'field_test_1_sum' => 1, 'field_test_1_count' => 1],
343 ['user_id' => 2, 'field_test_1_sum' => 5, 'field_test_1_count' => 3],
344 ['user_id' => 3, 'field_test_1_sum' => 5, 'field_test_1_count' => 2],
347 // Group by and aggregate by a fieldapi field.
348 $this->queryResult = $this->factory->getAggregate('entity_test')
349 ->groupBy('field_test_1')
350 ->aggregate('field_test_2', 'COUNT')
352 $this->assertResults([
353 ['field_test_1' => 1, 'field_test_2_count' => 2],
354 ['field_test_1' => 2, 'field_test_2_count' => 3],
355 ['field_test_1' => 3, 'field_test_2_count' => 1],
358 // Group by and aggregate by a fieldapi field and use multiple aggregate
360 $this->queryResult = $this->factory->getAggregate('entity_test')
361 ->groupBy('field_test_1')
362 ->aggregate('field_test_2', 'COUNT')
363 ->aggregate('field_test_2', 'SUM')
365 $this->assertResults([
366 ['field_test_1' => 1, 'field_test_2_count' => 2, 'field_test_2_sum' => 9],
367 ['field_test_1' => 2, 'field_test_2_count' => 3, 'field_test_2_sum' => 11],
368 ['field_test_1' => 3, 'field_test_2_count' => 1, 'field_test_2_sum' => 8],
371 // Apply an aggregate condition for a fieldapi field and group by a simple
373 $this->queryResult = $this->factory->getAggregate('entity_test')
374 ->conditionAggregate('field_test_1', 'COUNT', 3)
377 $this->assertResults([
378 ['user_id' => 2, 'field_test_1_count' => 3],
379 ['user_id' => 3, 'field_test_1_count' => 2],
382 $this->queryResult = $this->factory->getAggregate('entity_test')
383 ->aggregate('field_test_1', 'SUM')
384 ->conditionAggregate('field_test_1', 'COUNT', 2, '>')
387 $this->assertResults([
388 ['user_id' => 2, 'field_test_1_sum' => 5, 'field_test_1_count' => 3],
389 ['user_id' => 3, 'field_test_1_sum' => 5, 'field_test_1_count' => 2],
392 // Apply an aggregate condition for a simple property and a group by a
394 $this->queryResult = $this->factory->getAggregate('entity_test')
395 ->conditionAggregate('user_id', 'COUNT', 2)
396 ->groupBy('field_test_1')
398 $this->assertResults([
399 ['field_test_1' => 1, 'user_id_count' => 2],
402 $this->queryResult = $this->factory->getAggregate('entity_test')
403 ->conditionAggregate('user_id', 'COUNT', 2, '>')
404 ->groupBy('field_test_1')
406 $this->assertResults([
407 ['field_test_1' => 1, 'user_id_count' => 2],
408 ['field_test_1' => 2, 'user_id_count' => 3],
411 // Apply an aggregate condition and a group by fieldapi fields.
412 $this->queryResult = $this->factory->getAggregate('entity_test')
413 ->groupBy('field_test_1')
414 ->conditionAggregate('field_test_2', 'COUNT', 2)
416 $this->assertResults([
417 ['field_test_1' => 1, 'field_test_2_count' => 2],
419 $this->queryResult = $this->factory->getAggregate('entity_test')
420 ->groupBy('field_test_1')
421 ->conditionAggregate('field_test_2', 'COUNT', 2, '>')
423 $this->assertResults([
424 ['field_test_1' => 1, 'field_test_2_count' => 2],
425 ['field_test_1' => 2, 'field_test_2_count' => 3],
428 // Apply an aggregate condition and a group by fieldapi fields with multiple
429 // conditions via AND.
430 $this->queryResult = $this->factory->getAggregate('entity_test')
431 ->groupBy('field_test_1')
432 ->conditionAggregate('field_test_2', 'COUNT', 2)
433 ->conditionAggregate('field_test_2', 'SUM', 8)
435 $this->assertResults([]);
437 // Apply an aggregate condition and a group by fieldapi fields with multiple
438 // conditions via OR.
439 $this->queryResult = $this->factory->getAggregate('entity_test', 'OR')
440 ->groupBy('field_test_1')
441 ->conditionAggregate('field_test_2', 'COUNT', 2)
442 ->conditionAggregate('field_test_2', 'SUM', 8)
444 $this->assertResults([
445 ['field_test_1' => 1, 'field_test_2_count' => 2, 'field_test_2_sum' => 9],
446 ['field_test_1' => 3, 'field_test_2_count' => 1, 'field_test_2_sum' => 8],
449 // Group by a normal property and aggregate a fieldapi field and sort by the
451 $this->queryResult = $this->factory->getAggregate('entity_test')
452 ->aggregate('field_test_1', 'COUNT')
454 ->sort('user_id', 'DESC')
456 $this->assertSortedResults([
457 ['user_id' => 3, 'field_test_1_count' => 2],
458 ['user_id' => 2, 'field_test_1_count' => 3],
459 ['user_id' => 1, 'field_test_1_count' => 1],
462 $this->queryResult = $this->factory->getAggregate('entity_test')
463 ->aggregate('field_test_1', 'COUNT')
465 ->sort('user_id', 'ASC')
467 $this->assertSortedResults([
468 ['user_id' => 1, 'field_test_1_count' => 1],
469 ['user_id' => 2, 'field_test_1_count' => 3],
470 ['user_id' => 3, 'field_test_1_count' => 2],
473 $this->queryResult = $this->factory->getAggregate('entity_test')
474 ->conditionAggregate('field_test_1', 'COUNT', 2, '>')
476 ->sort('user_id', 'ASC')
478 $this->assertSortedResults([
479 ['user_id' => 2, 'field_test_1_count' => 3],
480 ['user_id' => 3, 'field_test_1_count' => 2],
483 // Group by a normal property, aggregate a fieldapi field, and sort by the
485 $this->queryResult = $this->factory->getAggregate('entity_test')
486 ->sortAggregate('field_test_1', 'COUNT', 'DESC')
489 $this->assertSortedResults([
490 ['user_id' => 2, 'field_test_1_count' => 3],
491 ['user_id' => 3, 'field_test_1_count' => 2],
492 ['user_id' => 1, 'field_test_1_count' => 1],
495 $this->queryResult = $this->factory->getAggregate('entity_test')
496 ->sortAggregate('field_test_1', 'COUNT', 'ASC')
499 $this->assertSortedResults([
500 ['user_id' => 1, 'field_test_1_count' => 1],
501 ['user_id' => 3, 'field_test_1_count' => 2],
502 ['user_id' => 2, 'field_test_1_count' => 3],
505 // Group by and aggregate by fieldapi field, and sort by the groupby field.
506 $this->queryResult = $this->factory->getAggregate('entity_test')
507 ->groupBy('field_test_1')
508 ->aggregate('field_test_2', 'COUNT')
509 ->sort('field_test_1', 'ASC')
511 $this->assertSortedResults([
512 ['field_test_1' => 1, 'field_test_2_count' => 2],
513 ['field_test_1' => 2, 'field_test_2_count' => 3],
514 ['field_test_1' => 3, 'field_test_2_count' => 1],
517 $this->queryResult = $this->factory->getAggregate('entity_test')
518 ->groupBy('field_test_1')
519 ->aggregate('field_test_2', 'COUNT')
520 ->sort('field_test_1', 'DESC')
522 $this->assertSortedResults([
523 ['field_test_1' => 3, 'field_test_2_count' => 1],
524 ['field_test_1' => 2, 'field_test_2_count' => 3],
525 ['field_test_1' => 1, 'field_test_2_count' => 2],
528 // Groupby and aggregate by fieldapi field, and sort by the aggregated
530 $this->queryResult = $this->factory->getAggregate('entity_test')
531 ->groupBy('field_test_1')
532 ->sortAggregate('field_test_2', 'COUNT', 'DESC')
534 $this->assertSortedResults([
535 ['field_test_1' => 2, 'field_test_2_count' => 3],
536 ['field_test_1' => 1, 'field_test_2_count' => 2],
537 ['field_test_1' => 3, 'field_test_2_count' => 1],
540 $this->queryResult = $this->factory->getAggregate('entity_test')
541 ->groupBy('field_test_1')
542 ->sortAggregate('field_test_2', 'COUNT', 'ASC')
544 $this->assertSortedResults([
545 ['field_test_1' => 3, 'field_test_2_count' => 1],
546 ['field_test_1' => 1, 'field_test_2_count' => 2],
547 ['field_test_1' => 2, 'field_test_2_count' => 3],
553 * Asserts the results as expected regardless of order between and in rows.
555 * @param array $expected
556 * An array of the expected results.
558 protected function assertResults($expected, $sorted = FALSE) {
560 $expected_keys = array_keys($expected);
561 foreach ($this->queryResult as $key => $row) {
562 $keys = $sorted ? [$key] : $expected_keys;
563 foreach ($keys as $key) {
564 $expected_row = $expected[$key];
565 if (!array_diff_assoc($row, $expected_row) && !array_diff_assoc($expected_row, $row)) {
572 return $this->assertTrue($found, strtr('!expected expected, !found found', ['!expected' => print_r($expected, TRUE), '!found' => print_r($this->queryResult, TRUE)]));
576 * Asserts the results as expected regardless of order in rows.
578 * @param array $expected
579 * An array of the expected results.
581 protected function assertSortedResults($expected) {
582 return $this->assertResults($expected, TRUE);