Skip to content

Commit b9f8a9a

Browse files
author
Holger Lösken
committed
Allowing different entities indexed into same index
1 parent 2643cb5 commit b9f8a9a

25 files changed

+475
-429
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@
44
.phpunit.result.cache
55
/var/
66
.php-cs-fixer.cache
7-
/tests/cache/blog.sqlite

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"php": "^7.4|^8.0",
2222
"ext-json": "*",
2323
"doctrine/doctrine-bundle": "^2.4",
24+
"illuminate/collections": "^8.47",
2425
"meilisearch/meilisearch-php": "^0.18",
2526
"symfony/filesystem": "^4.0 || ^5.0",
2627
"symfony/property-access": "^4.0 || ^5.0",

phpunit.xml.dist

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<phpunit colors="true" bootstrap="vendor/autoload.php" convertDeprecationsToExceptions="false">
3-
<php>
4-
<env name="KERNEL_CLASS" value="MeiliSearch\Bundle\Test\Kernel"/>
5-
<env name="APP_ENV" value="test"/>
6-
<env name="APP_DEBUG" value="false"/>
7-
<env name="MEILISEARCH_PREFIX" value="sf_phpunit_"/>
8-
<env name="MEILISEARCH_URL" value="http://127.0.0.1:7700"/>
9-
<env name="MEILISEARCH_API_KEY" value="masterKey"/>
10-
<env name="TRAVIS_JOB_NUMBER" value=""/>
11-
<env name="SYMFONY_DEPRECATIONS_HELPER" value="disabled"/>
12-
</php>
13-
<testsuites>
14-
<testsuite name="TestCase">
15-
<directory suffix=".php">tests/TestCase/</directory>
16-
</testsuite>
17-
</testsuites>
18-
<filter>
19-
<whitelist>
20-
<directory>src/</directory>
21-
<exclude>
22-
<file>src/DependencyInjection/MeiliSearchExtension.php</file>
23-
<file>src/Services/NullSearchService.php</file>
24-
</exclude>
25-
</whitelist>
26-
</filter>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" colors="true" bootstrap="vendor/autoload.php" convertDeprecationsToExceptions="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
3+
<coverage>
4+
<include>
5+
<directory>src/</directory>
6+
</include>
7+
<exclude>
8+
<file>src/DependencyInjection/MeiliSearchExtension.php</file>
9+
<file>src/Services/NullSearchService.php</file>
10+
</exclude>
11+
</coverage>
12+
<php>
13+
<env name="KERNEL_CLASS" value="MeiliSearch\Bundle\Test\Kernel"/>
14+
<env name="APP_ENV" value="test"/>
15+
<env name="APP_DEBUG" value="false"/>
16+
<env name="MEILISEARCH_PREFIX" value="sf_phpunit_"/>
17+
<env name="MEILISEARCH_URL" value="http://127.0.0.1:7700"/>
18+
<env name="MEILISEARCH_API_KEY" value="masterKey"/>
19+
<env name="TRAVIS_JOB_NUMBER" value=""/>
20+
<env name="SYMFONY_DEPRECATIONS_HELPER" value="disabled"/>
21+
</php>
22+
<testsuites>
23+
<testsuite name="TestCase">
24+
<directory suffix=".php">tests/TestCase/</directory>
25+
</testsuite>
26+
</testsuites>
2727
</phpunit>

src/Command/IndexCommand.php

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace MeiliSearch\Bundle\Command;
66

7+
use Illuminate\Support\Collection;
78
use MeiliSearch\Bundle\SearchService;
89
use Symfony\Component\Console\Command\Command;
910
use Symfony\Component\Console\Input\InputInterface;
@@ -14,28 +15,47 @@
1415
*/
1516
abstract class IndexCommand extends Command
1617
{
18+
private string $prefix;
1719
protected SearchService $searchService;
1820

1921
public function __construct(SearchService $searchService, ?string $name = null)
2022
{
2123
$this->searchService = $searchService;
24+
$this->prefix = $this->searchService->getConfiguration()->get('prefix');
25+
2226
parent::__construct($name);
2327
}
2428

25-
protected function getEntitiesFromArgs(InputInterface $input, OutputInterface $output): array
29+
protected function getIndices(): Collection
30+
{
31+
return collect($this->searchService->getConfiguration()->get('indices'))
32+
->transform(function (array $item) {
33+
$item['name'] = $this->prefix.$item['name'];
34+
35+
return $item;
36+
});
37+
}
38+
39+
protected function getEntitiesFromArgs(InputInterface $input, OutputInterface $output): Collection
2640
{
27-
$entities = [];
28-
$indexNames = [];
41+
$indexNames = collect();
2942

3043
if ($indexList = $input->getOption('indices')) {
31-
$indexNames = \explode(',', $indexList);
44+
$list = \explode(',', $indexList);
45+
$indexNames = collect($list)->transform(function (string $item) {
46+
// Check if the given index name already contains the prefix
47+
if(strpos($item, $this->prefix) === false) {
48+
return $this->prefix.$item;
49+
}
50+
51+
return $item;
52+
});
3253
}
3354

3455
$config = $this->searchService->getConfiguration();
3556

36-
if ((0 === count($indexNames))
37-
&& !empty(array_keys($config['indices']))) {
38-
$indexNames = array_keys($config['indices']);
57+
if ((0 === count($indexNames)) && count($config->get('indices')) > 0) {
58+
$indexNames = $this->getIndices();
3959
}
4060

4161
if (0 === count($indexNames)) {
@@ -44,19 +64,8 @@ protected function getEntitiesFromArgs(InputInterface $input, OutputInterface $o
4464
);
4565
}
4666

47-
foreach ($indexNames as $name) {
48-
if (isset($config['indices'][$name])) {
49-
$entities[$name]['name'] = $config['indices'][$name]['class'];
50-
if (true === $input->hasOption('update-settings') && !empty($config['indices'][$name]['settings'])) {
51-
$entities[$name]['settings'] = $config['indices'][$name]['settings'];
52-
}
53-
} else {
54-
$output->writeln(
55-
'<comment>No index named <info>'.$name.'</info> was found. Check you configuration.</comment>'
56-
);
57-
}
58-
}
59-
60-
return $entities;
67+
return collect($this->getIndices())->reject(function (array $item) use ($indexNames) {
68+
return !in_array($item['name'], $indexNames->toArray(), true);
69+
});
6170
}
6271
}

src/Command/MeiliSearchClearCommand.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,22 @@ protected function execute(InputInterface $input, OutputInterface $output): int
2626
{
2727
$indexToClear = $this->getEntitiesFromArgs($input, $output);
2828

29-
foreach ($indexToClear as $indexName => $entity) {
30-
$className = $entity['name'];
29+
/** @var array $index */
30+
foreach ($indexToClear as $index) {
31+
$indexName = $index['name'];
32+
$className = $index['class'];
3133
$array = $this->searchService->clear($className);
3234
if ('failed' === $array['status']) {
3335
$output->writeln('<error>Index <info>'.$indexName.'</info> couldn\'t be cleared</error>');
3436
} else {
35-
$output->writeln(
36-
'Cleared <info>'.$indexName.'</info> index of <comment>'.$className.'</comment> '
37-
);
37+
$output->writeln('Cleared <info>'.$indexName.'</info> index of <comment>'.$className.'</comment>');
3838
}
3939
}
4040

41+
if (0 === count($indexToClear)) {
42+
$output->writeln('Cannot clear index. Not found.');
43+
}
44+
4145
$output->writeln('<info>Done!</info>');
4246

4347
return 0;

src/Command/MeiliSearchImportCommand.php

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,43 +45,47 @@ protected function configure()
4545

4646
protected function execute(InputInterface $input, OutputInterface $output): int
4747
{
48-
$entitiesToIndex = $this->getEntitiesFromArgs($input, $output);
48+
$indexes = $this->getEntitiesFromArgs($input, $output);
4949
$config = $this->searchService->getConfiguration();
5050

51-
foreach ($entitiesToIndex as $key => $entity) {
52-
$entityClassName = $entity['name'];
51+
foreach ($indexes as $key => $index) {
52+
$entityClassName = $index['class'];
5353
if (is_subclass_of($entityClassName, Aggregator::class)) {
54-
unset($entitiesToIndex[$key]);
55-
$entitiesToIndex = array_merge(
56-
$entitiesToIndex,
54+
$indexes->forget($key);
55+
56+
$indexes = collect(array_merge(
57+
$indexes->toArray(),
5758
array_map(
5859
function ($entity) {
59-
return ['name' => $entity];
60+
return ['class' => $entity];
6061
},
6162
$entityClassName::getEntities()
6263
)
63-
);
64+
));
6465
}
6566
}
6667

67-
$entitiesToIndex = array_unique($entitiesToIndex, SORT_REGULAR);
68+
$entitiesToIndex = array_unique($indexes->toArray(), SORT_REGULAR);
6869

69-
foreach ($entitiesToIndex as $index => $entity) {
70-
$entityClassName = $entity['name'];
70+
/** @var array $index */
71+
foreach ($entitiesToIndex as $index) {
72+
$entityClassName = $index['class'];
7173
if (!$this->searchService->isSearchable($entityClassName)) {
7274
continue;
7375
}
7476

7577
$manager = $this->managerRegistry->getManagerForClass($entityClassName);
7678
$repository = $manager->getRepository($entityClassName);
7779

80+
$output->writeln('<info>Importing for index '.$entityClassName.'</info>');
81+
7882
$page = 0;
7983
do {
8084
$entities = $repository->findBy(
8185
[],
8286
null,
83-
$config['batchSize'],
84-
$config['batchSize'] * $page
87+
$config->get('batchSize'),
88+
$config->get('batchSize') * $page
8589
);
8690

8791
$responses = $this->formatIndexingResponse($this->searchService->index($manager, $entities));
@@ -97,9 +101,9 @@ function ($entity) {
97101
);
98102
}
99103

100-
if (!empty($entity['settings'])) {
101-
$indexInstance = $this->searchClient->getOrCreateIndex($config['prefix'].$index);
102-
foreach ($entity['settings'] as $variable => $value) {
104+
if (!empty($index['settings'])) {
105+
$indexInstance = $this->searchClient->getOrCreateIndex($index['name']);
106+
foreach ($index['settings'] as $variable => $value) {
103107
$method = sprintf('update%s', ucfirst($variable));
104108
if (false === method_exists($indexInstance, $method)) {
105109
throw new InvalidSettingName(sprintf('Invalid setting name: "%s"', $variable));
@@ -114,12 +118,14 @@ function ($entity) {
114118

115119
if ('failed' === $updateStatus['status']) {
116120
throw new UpdateException($updateStatus['error']);
121+
} else {
122+
$output->writeln('<info>Settings updated.</info>');
117123
}
118124
}
119125
}
120126

121127
++$page;
122-
} while (count($entities) >= $config['batchSize']);
128+
} while (count($entities) >= $config->get('batchSize'));
123129

124130
$manager->clear();
125131
}

src/DependencyInjection/Configuration.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,12 @@ public function getConfigTreeBuilder(): TreeBuilder
3838
->defaultValue('serializer')
3939
->end()
4040
->arrayNode('indices')
41-
->useAttributeAsKey('name')
4241
->arrayPrototype()
4342
->children()
43+
->scalarNode('name')
44+
->isRequired()
45+
->cannotBeEmpty()
46+
->end()
4447
->scalarNode('class')
4548
->isRequired()
4649
->cannotBeEmpty()

src/Engine.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public function __construct(Client $client)
3232
public function index($searchableEntities): array
3333
{
3434
if ($searchableEntities instanceof SearchableEntity) {
35+
/** @var SearchableEntity[] $searchableEntities */
3536
$searchableEntities = [$searchableEntities];
3637
}
3738

@@ -70,10 +71,13 @@ public function index($searchableEntities): array
7071
public function remove($searchableEntities): array
7172
{
7273
if ($searchableEntities instanceof SearchableEntity) {
74+
/** @var SearchableEntity[] $searchableEntities */
7375
$searchableEntities = [$searchableEntities];
7476
}
7577

7678
$data = [];
79+
80+
/** @var SearchableEntity $entity */
7781
foreach ($searchableEntities as $entity) {
7882
$searchableArray = $entity->getSearchableArray();
7983
if (null === $searchableArray || 0 === \count($searchableArray)) {
@@ -137,6 +141,6 @@ public function search(string $query, string $indexUid, array $searchParams): ar
137141
*/
138142
public function count(string $query, string $indexName, array $searchParams): int
139143
{
140-
return (int) $this->client->index($indexName)->search($query, $searchParams)['nbHits'];
144+
return $this->client->index($indexName)->search($query, $searchParams)->getHitsCount();
141145
}
142146
}

src/Exception/InvalidEntityForAggregator.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44

55
namespace MeiliSearch\Bundle\Exception;
66

7-
/**
8-
* Class InvalidEntityForAggregator.
9-
*/
107
final class InvalidEntityForAggregator extends \LogicException
118
{
129
}

src/SearchService.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace MeiliSearch\Bundle;
66

77
use Doctrine\Persistence\ObjectManager;
8+
use Illuminate\Support\Collection;
89

910
/**
1011
* Interface SearchService.
@@ -21,7 +22,7 @@ public function isSearchable($className): bool;
2122

2223
public function getSearchable(): array;
2324

24-
public function getConfiguration(): array;
25+
public function getConfiguration(): Collection;
2526

2627
/**
2728
* Get the index name for the given `$className`.
@@ -36,6 +37,8 @@ public function clear(string $className): array;
3637

3738
public function delete(string $className): ?array;
3839

40+
public function deleteByIndexName(string $indexName): ?array;
41+
3942
public function search(
4043
ObjectManager $objectManager,
4144
string $className,

src/SearchableEntity.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public function __construct(
5151
$this->setId();
5252
}
5353

54-
public function getindexUid(): string
54+
public function getIndexUid(): string
5555
{
5656
return $this->indexUid;
5757
}

0 commit comments

Comments
 (0)