Skip to content

Commit 3a9033e

Browse files
committed
Normalize entity id before index or remove
Normalize entity id before index or remove Normalize entity id before index or remove
1 parent 3834324 commit 3a9033e

File tree

8 files changed

+185
-4
lines changed

8 files changed

+185
-4
lines changed

src/Engine.php

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

55
namespace MeiliSearch\Bundle;
66

7-
use function count;
87
use MeiliSearch\Client;
98
use MeiliSearch\Exceptions\ApiException;
109

@@ -49,7 +48,7 @@ public function index($searchableEntities): array
4948
$data[$indexUid] = [];
5049
}
5150

52-
$data[$indexUid][] = $searchableArray + ['objectID' => $entity->getId()];
51+
$data[$indexUid][] = $searchableArray + ['objectID' => $this->normalizeId($entity->getId())];
5352
}
5453

5554
$result = [];
@@ -89,7 +88,7 @@ public function remove($searchableEntities): array
8988
$data[$indexUid] = [];
9089
}
9190

92-
$data[$indexUid][] = $entity->getId();
91+
$data[$indexUid][] = $this->normalizeId($entity->getId());
9392
}
9493

9594
$result = [];
@@ -143,4 +142,13 @@ public function count(string $query, string $indexName, array $searchParams): in
143142
{
144143
return $this->client->index($indexName)->search($query, $searchParams)->getHitsCount();
145144
}
145+
146+
private function normalizeId($id)
147+
{
148+
if (is_object($id) && method_exists($id, '__toString')) {
149+
return (string) $id;
150+
}
151+
152+
return $id;
153+
}
146154
}

src/Services/MeiliSearchService.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ public function search(
177177
}
178178

179179
$repo = $objectManager->getRepository($entityClass);
180-
$entity = $repo->findOneBy(['id' => $id]);
180+
$entity = $repo->find($id);
181181

182182
if (null !== $entity) {
183183
$results[] = $entity;

tests/BaseKernelTestCase.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
use MeiliSearch\Bundle\Test\Entity\Comment;
1212
use MeiliSearch\Bundle\Test\Entity\Image;
1313
use MeiliSearch\Bundle\Test\Entity\Link;
14+
use MeiliSearch\Bundle\Test\Entity\ObjectId\DummyObjectId;
15+
use MeiliSearch\Bundle\Test\Entity\Page;
1416
use MeiliSearch\Bundle\Test\Entity\Post;
1517
use MeiliSearch\Bundle\Test\Entity\Tag;
1618
use MeiliSearch\Exceptions\ApiException;
@@ -54,6 +56,19 @@ protected function createPost($id = null): Post
5456
return $post;
5557
}
5658

59+
protected function createPage(int $id): Page
60+
{
61+
$page = new Page();
62+
$page->setTitle('Test Page');
63+
$page->setContent('Test content page');
64+
$page->setId(new DummyObjectId($id));
65+
66+
$this->entityManager->persist($page);
67+
$this->entityManager->flush();
68+
69+
return $page;
70+
}
71+
5772
protected function createSearchablePost(): SearchableEntity
5873
{
5974
$post = $this->createPost(random_int(100, 300));
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MeiliSearch\Bundle\Test\Entity\ObjectId;
6+
7+
class DummyObjectId
8+
{
9+
private int $id;
10+
11+
public function __construct(int $id)
12+
{
13+
$this->id = $id;
14+
}
15+
16+
public function __toString()
17+
{
18+
return (string) $this->id;
19+
}
20+
}

tests/Entity/Page.php

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MeiliSearch\Bundle\Test\Entity;
6+
7+
use Doctrine\ORM\Mapping as ORM;
8+
use Symfony\Component\Serializer\Annotation\Groups;
9+
10+
/**
11+
* @ORM\Entity
12+
* @ORM\Table(name="pages")
13+
*/
14+
class Page
15+
{
16+
/**
17+
* @ORM\Id
18+
* @ORM\GeneratedValue(strategy="NONE")
19+
* @ORM\Column(type="object")
20+
*/
21+
private $id = null;
22+
23+
/**
24+
* @ORM\Column(type="string", nullable=true)
25+
* @Groups({"searchable"})
26+
*/
27+
private ?string $title = null;
28+
29+
/**
30+
* @ORM\Column(type="text", nullable=true)
31+
* @Groups({"searchable"})
32+
*/
33+
private ?string $content = null;
34+
35+
public function getId()
36+
{
37+
return $this->id;
38+
}
39+
40+
public function setId($id): self
41+
{
42+
$this->id = $id;
43+
44+
return $this;
45+
}
46+
47+
public function getTitle(): ?string
48+
{
49+
return $this->title;
50+
}
51+
52+
public function setTitle(?string $title): self
53+
{
54+
$this->title = $title;
55+
56+
return $this;
57+
}
58+
59+
public function getContent(): ?string
60+
{
61+
return $this->content;
62+
}
63+
64+
public function setContent(?string $content): self
65+
{
66+
$this->content = $content;
67+
68+
return $this;
69+
}
70+
}

tests/Integration/CommandsTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ public function testSearchImportAndClearWithoutIndices(): void
5757
$this->createPost();
5858
}
5959

60+
for ($i = 0; $i <= 5; ++$i) {
61+
$this->createPage($i);
62+
}
63+
6064
for ($i = 0; $i <= 5; ++$i) {
6165
$this->createTag(['id' => $i]);
6266
}
@@ -78,6 +82,8 @@ public function testSearchImportAndClearWithoutIndices(): void
7882
Indexed 6 / 6 MeiliSearch\Bundle\Test\Entity\Tag entities into sf_phpunit__tags index
7983
Indexed 6 / 6 MeiliSearch\Bundle\Test\Entity\Tag entities into sf_phpunit__aggregated index
8084
Importing for index MeiliSearch\Bundle\Test\Entity\Link
85+
Importing for index MeiliSearch\Bundle\Test\Entity\Page
86+
Indexed 6 / 6 MeiliSearch\Bundle\Test\Entity\Page entities into sf_phpunit__pages index
8187
Importing for index MeiliSearch\Bundle\Test\Entity\Post
8288
Indexed 6 / 6 MeiliSearch\Bundle\Test\Entity\Post entities into sf_phpunit__posts index
8389
Indexed 6 / 6 MeiliSearch\Bundle\Test\Entity\Post entities into sf_phpunit__aggregated index
@@ -100,6 +106,7 @@ public function testSearchImportAndClearWithoutIndices(): void
100106
Cleared sf_phpunit__aggregated index of MeiliSearch\Bundle\Test\Entity\ContentAggregator
101107
Cleared sf_phpunit__tags index of MeiliSearch\Bundle\Test\Entity\Tag
102108
Cleared sf_phpunit__tags index of MeiliSearch\Bundle\Test\Entity\Link
109+
Cleared sf_phpunit__pages index of MeiliSearch\Bundle\Test\Entity\Page
103110
Done!
104111

105112
EOD, $clearOutput);

tests/Integration/EventListener/DoctrineEventSubscriberTest.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Doctrine\ORM\Event\LifecycleEventArgs;
88
use MeiliSearch\Bundle\EventListener\DoctrineEventSubscriber;
99
use MeiliSearch\Bundle\Test\BaseKernelTestCase;
10+
use MeiliSearch\Bundle\Test\Entity\Page;
1011
use MeiliSearch\Bundle\Test\Entity\Post;
1112

1213
class DoctrineEventSubscriberTest extends BaseKernelTestCase
@@ -30,6 +31,23 @@ public function testPostPersist(): void
3031
$this->assertSame(2, $result[0]->getId());
3132
}
3233

34+
public function testPostPersistWithObjectId(): void
35+
{
36+
$this->createPage(1);
37+
$page = $this->createPage(2);
38+
39+
$eventArgs = new LifecycleEventArgs($page, $this->entityManager);
40+
41+
$subscriber = new DoctrineEventSubscriber($this->searchService, []);
42+
$subscriber->postPersist($eventArgs);
43+
sleep(1);
44+
45+
$result = $this->searchService->search($this->entityManager, Page::class, $page->getTitle());
46+
47+
$this->assertCount(1, $result);
48+
$this->assertSame((string) $page->getId(), (string) $result[0]->getId());
49+
}
50+
3351
/**
3452
* This tests creates two posts in the database, but only one is triggered via an event to MS.
3553
*/
@@ -49,6 +67,23 @@ public function testPostUpdate(): void
4967
$this->assertSame(2, $result[0]->getId());
5068
}
5169

70+
public function testPostUpdateWithObjectId(): void
71+
{
72+
$this->createPage(1);
73+
$page = $this->createPage(2);
74+
75+
$eventArgs = new LifecycleEventArgs($page, $this->entityManager);
76+
77+
$subscriber = new DoctrineEventSubscriber($this->searchService, []);
78+
$subscriber->postUpdate($eventArgs);
79+
sleep(1);
80+
81+
$result = $this->searchService->search($this->entityManager, Page::class, $page->getTitle());
82+
83+
$this->assertCount(1, $result);
84+
$this->assertSame((string) $page->getId(), (string) $result[0]->getId());
85+
}
86+
5287
/**
5388
* This tests creates posts in the database, send it to MS via a trigger. Afterwards Doctrines 'preRemove' event
5489
* is going to remove that entity from MS.
@@ -79,4 +114,27 @@ public function testPreRemove(): void
79114

80115
$this->assertCount(0, $result);
81116
}
117+
118+
public function testPreRemoveWithObjectId(): void
119+
{
120+
$page = $this->createPage(1);
121+
122+
$eventArgs = new LifecycleEventArgs($page, $this->entityManager);
123+
124+
$subscriber = new DoctrineEventSubscriber($this->searchService, []);
125+
$subscriber->postPersist($eventArgs);
126+
sleep(1);
127+
128+
$result = $this->searchService->search($this->entityManager, Page::class, $page->getTitle());
129+
130+
$this->assertCount(1, $result);
131+
$this->assertSame((string) $page->getId(), (string) $result[0]->getId());
132+
133+
$subscriber->preRemove($eventArgs);
134+
sleep(1);
135+
136+
$result = $this->searchService->search($this->entityManager, Page::class, $page->getTitle());
137+
138+
$this->assertCount(0, $result);
139+
}
82140
}

tests/config/meili_search.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ meili_search:
2424
- name: tags
2525
class: 'MeiliSearch\Bundle\Test\Entity\Link'
2626
index_if: isSponsored
27+
- name: pages
28+
class: 'MeiliSearch\Bundle\Test\Entity\Page'
29+
enable_serializer_groups: true

0 commit comments

Comments
 (0)