-
-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add sorting of results #12
Changes from all commits
ea60295
7fd56ea
45ac62f
221f7f6
a9f3d08
74580c8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Setono\SyliusMeilisearchPlugin\Engine; | ||
|
||
use Meilisearch\Client; | ||
use Meilisearch\Search\SearchResult; | ||
use Setono\SyliusMeilisearchPlugin\Config\Index; | ||
use Setono\SyliusMeilisearchPlugin\Document\Metadata\Facet; | ||
use Setono\SyliusMeilisearchPlugin\Document\Metadata\MetadataFactoryInterface; | ||
use Setono\SyliusMeilisearchPlugin\Meilisearch\Builder\FilterBuilderInterface; | ||
use Setono\SyliusMeilisearchPlugin\Resolver\IndexName\IndexNameResolverInterface; | ||
|
||
final class SearchEngine implements SearchEngineInterface | ||
{ | ||
public function __construct( | ||
private readonly MetadataFactoryInterface $metadataFactory, | ||
private readonly FilterBuilderInterface $filterBuilder, | ||
private readonly Index $index, | ||
private readonly IndexNameResolverInterface $indexNameResolver, | ||
private readonly Client $client, | ||
private readonly int $hitsPerPage, | ||
) { | ||
} | ||
|
||
public function execute(?string $query, array $parameters = []): SearchResult | ||
{ | ||
$page = max(1, (int) ($parameters['p'] ?? 1)); | ||
$sort = (string) ($parameters['sort'] ?? ''); | ||
|
||
$metadata = $this->metadataFactory->getMetadataFor($this->index->document); | ||
|
||
$searchParams = [ | ||
'facets' => array_map(static fn (Facet $facet) => $facet->name, $metadata->getFacets()), | ||
'filter' => $this->filterBuilder->build($parameters), | ||
'hitsPerPage' => $this->hitsPerPage, | ||
'page' => $page, | ||
]; | ||
if ('' !== $sort) { | ||
$searchParams['sort'] = [$sort]; | ||
} | ||
|
||
return $this->client->index($this->indexNameResolver->resolve($this->index))->search($query, $searchParams); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Setono\SyliusMeilisearchPlugin\Engine; | ||
|
||
use Meilisearch\Search\SearchResult; | ||
|
||
interface SearchEngineInterface | ||
{ | ||
public function execute(?string $query, array $parameters = []): SearchResult; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Setono\SyliusMeilisearchPlugin\Tests\Functional; | ||
|
||
use Setono\SyliusMeilisearchPlugin\Engine\SearchEngine; | ||
use Symfony\Bundle\FrameworkBundle\KernelBrowser; | ||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; | ||
|
||
/** @group functional */ | ||
final class SearchTest extends WebTestCase | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very nice to have tests! :D |
||
{ | ||
private static KernelBrowser $client; | ||
|
||
protected function setUp(): void | ||
{ | ||
parent::setUp(); | ||
|
||
self::ensureKernelShutdown(); | ||
self::$client = static::createClient(['environment' => 'test', 'debug' => true]); | ||
} | ||
|
||
public function testItProvidesSearchResults(): void | ||
{ | ||
/** @var SearchEngine $searchEngine */ | ||
$searchEngine = self::getContainer()->get(SearchEngine::class); | ||
$result = $searchEngine->execute('jeans'); | ||
|
||
self::assertSame(8, $result->getHitsCount()); | ||
} | ||
|
||
public function testItSortsSearchResultsByLowestPrice(): void | ||
{ | ||
/** @var SearchEngine $searchEngine */ | ||
$searchEngine = self::getContainer()->get(SearchEngine::class); | ||
$result = $searchEngine->execute('jeans', ['sort' => 'price:asc']); | ||
|
||
self::assertSame(8, $result->getHitsCount()); | ||
|
||
$previousKey = null; | ||
foreach ($result->getHits() as $key => $hit) { | ||
if ($previousKey === null) { | ||
$previousKey = $key; | ||
|
||
continue; | ||
} | ||
|
||
$previousHit = (array) $result->getHit($previousKey); | ||
self::assertGreaterThanOrEqual($previousHit['price'], $hit['price']); | ||
$previousKey = $key; | ||
} | ||
} | ||
|
||
public function testItSortsSearchResultsByNewestDate(): void | ||
{ | ||
/** @var SearchEngine $searchEngine */ | ||
$searchEngine = self::getContainer()->get(SearchEngine::class); | ||
$result = $searchEngine->execute('jeans', ['sort' => 'createdAt:desc']); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This small thing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO it shouldn't make any troubles. |
||
|
||
self::assertSame(8, $result->getHitsCount()); | ||
|
||
$previousKey = null; | ||
foreach ($result->getHits() as $key => $hit) { | ||
if ($previousKey === null) { | ||
$previousKey = $key; | ||
|
||
continue; | ||
} | ||
|
||
$previousHit = (array) $result->getHit($previousKey); | ||
self::assertLessThanOrEqual($previousHit['createdAt'], $hit['createdAt']); | ||
$previousKey = $key; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's easier to use suites, don't you? I think we did the same in the order edit plugin