Skip to content

Commit

Permalink
Add facetSearch function to Indexes
Browse files Browse the repository at this point in the history
  • Loading branch information
brunoocasali committed Jul 12, 2023
1 parent ef948fe commit eb909ac
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 0 deletions.
60 changes: 60 additions & 0 deletions src/Contracts/FacetSearchQuery.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

declare(strict_types=1);

namespace Meilisearch\Contracts;

class FacetSearchQuery
{
private ?string $q = null;
private ?string $matchingStrategy = null;
private ?array $filter = null;
private ?string $facetQuery = null;
private ?string $facetName = null;

public function setQuery(string $q): FacetSearchQuery
{
$this->q = $q;

return $this;
}

public function setMatchingStrategy(string $matchingStrategy): FacetSearchQuery
{
$this->matchingStrategy = $matchingStrategy;

return $this;
}

public function setFilter(string $filter): FacetSearchQuery
{
$this->filter = $filter;

return $this;
}

public function setFacetQuery(string $facetQuery): FacetSearchQuery
{
$this->facetQuery = $facetQuery;

return $this;
}

public function setFacetName(string $facetName): FacetSearchQuery
{
$this->facetName = $facetName;

return $this;
}

public function toArray(): array
{
return array_filter([
'q' => $this->q,
'matchingStrategy' => $this->matchingStrategy,
'filter' => $this->filter,
'facetQuery' => $this->facetQuery,
'facetName' => $this->facetName,
], function ($item) { return null !== $item; });
}
}
11 changes: 11 additions & 0 deletions src/Endpoints/Indexes.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Meilisearch\Endpoints;

use Meilisearch\Contracts\Endpoint;
use Meilisearch\Contracts\FacetSearchQuery;
use Meilisearch\Contracts\Http;
use Meilisearch\Contracts\Index\Settings;
use Meilisearch\Contracts\IndexesQuery;
Expand All @@ -15,6 +16,7 @@
use Meilisearch\Endpoints\Delegates\HandlesSettings;
use Meilisearch\Endpoints\Delegates\HandlesTasks;
use Meilisearch\Exceptions\ApiException;
use Meilisearch\Search\FacetSearchResult;
use Meilisearch\Search\SearchResult;

class Indexes extends Endpoint
Expand Down Expand Up @@ -211,6 +213,15 @@ public function rawSearch(?string $query, array $searchParams = []): array
return $result;
}

// Facet Search

public function facetSearch(FacetSearchQuery $params): FacetSearchResult
{
$response = $this->http->post(self::PATH.'/'.$this->uid.'/facet-search', $params->toArray());

return new FacetSearchResult($response);
}

// Stats

public function stats(): array
Expand Down
59 changes: 59 additions & 0 deletions src/Search/FacetSearchResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);

namespace Meilisearch\Search;

class FacetSearchResult implements \Countable, \IteratorAggregate
{
/**
* @var array<int, array<string, mixed>>
*/
private array $facetHits;
private int $processingTimeMs;
private ?string $facetQuery;

public function __construct(array $body)
{
$this->facetHits = $body['facetHits'] ?? [];
$this->facetQuery = $body['facetQuery'];
$this->processingTimeMs = $body['processingTimeMs'];
}

/**
* @return array<int, array>
*/
public function getFacetHits(): array
{
return $this->facetHits;
}

public function getProcessingTimeMs(): int
{
return $this->processingTimeMs;
}

public function toArray(): array
{
return [
'facetHits' => $this->facetHits,
'facetQuery' => $this->facetQuery,
'processingTimeMs' => $this->processingTimeMs,
];
}

public function toJSON(): string
{
return json_encode($this->toArray(), JSON_PRETTY_PRINT);
}

public function getIterator(): \ArrayIterator
{
return new \ArrayIterator($this->facetHits);
}

public function count(): int
{
return \count($this->facetHits);
}
}
42 changes: 42 additions & 0 deletions tests/Endpoints/FacetSearchTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace Tests\Endpoints;

use Meilisearch\Contracts\FacetSearchQuery;
use Meilisearch\Endpoints\Indexes;
use Tests\TestCase;

final class FacetSearchTest extends TestCase
{
private Indexes $index;

protected function setUp(): void
{
parent::setUp();

$this->index = $this->createEmptyIndex($this->safeIndexName());
$this->index->updateDocuments(self::DOCUMENTS);
$promise = $this->index->updateFilterableAttributes(['genre']);
$this->index->waitForTask($promise['taskUid']);
}

public function testBasicSearchWithFilters(): void
{
$response = $this->index->search('prince', ['facets' => ['genre']]);

$this->assertSame(array_keys($response->getFacetDistribution()['genre']), [
'adventure', 'fantasy',
]);

$response = $this->index->facetSearch(
(new FacetSearchQuery())
->setFacetQuery('fa')
->setFacetName('genre')
->setQuery('prince')
);

$this->assertSame(array_column($response->getFacetHits(), 'value'), ['fantasy']);
}
}

0 comments on commit eb909ac

Please sign in to comment.