Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/Typesense/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Statamic\Support\Arr;
use Typesense\Client;
use Typesense\Exceptions\ObjectNotFound;
use Typesense\Exceptions\TypesenseClientError;

class Index extends BaseIndex
{
Expand Down Expand Up @@ -121,6 +122,12 @@ public function searchUsingApi($query, array $options = []): array
$searchResults = $this->client->multiSearch->perform($searchRequest, []);
$searchResults = array_shift($searchResults['results']);

// Typesense answers with a 200 even when an individual search failed, so the error
// only shows up in the result itself.
if (! is_null($error = Arr::get($searchResults, 'error'))) {
throw new TypesenseClientError($error, (int) Arr::get($searchResults, 'code', 0));
}

$total = count($searchResults['hits']);

return [
Expand Down
69 changes: 69 additions & 0 deletions tests/Unit/SearchUsingApiTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

namespace StatamicRadPack\Typesense\Tests\Unit;

use Mockery;
use PHPUnit\Framework\Attributes\Test;
use StatamicRadPack\Typesense\Tests\TestCase;
use StatamicRadPack\Typesense\Typesense\Index;
use Typesense\ApiCall;
use Typesense\Client;
use Typesense\Collections;
use Typesense\Exceptions\TypesenseClientError;
use Typesense\MultiSearch;

class SearchUsingApiTest extends TestCase
{
private function indexWithMultiSearchResult(array $result, string $name = 'test'): Index
{
$apiCall = Mockery::mock(ApiCall::class);

$apiCall->shouldReceive('get')
->with('/collections/'.$name, [])
->andReturn(['name' => $name]);

$apiCall->shouldReceive('post')
->with('/multi_search', Mockery::type('array'), true, [])
->once()
->andReturn(['results' => [$result]]);

$client = new Client([
'api_key' => 'xyz',
'nodes' => [['host' => 'localhost', 'port' => '8108', 'path' => '', 'protocol' => 'http']],
]);

$client->collections = new Collections($apiCall);
$client->multiSearch = new MultiSearch($apiCall);

return new Index($client, $name, []);
}

#[Test]
public function it_throws_the_error_from_a_failed_search()
{
$index = $this->indexWithMultiSearchResult([
'code' => 400,
'error' => 'Could not find a filter field named `foo` in the schema.',
]);

$this->expectException(TypesenseClientError::class);
$this->expectExceptionMessage('Could not find a filter field named `foo` in the schema.');
$this->expectExceptionCode(400);

$index->searchUsingApi('*');
}

#[Test]
public function it_returns_the_hits_from_a_successful_search()
{
$index = $this->indexWithMultiSearchResult([
'hits' => [
['document' => ['id' => 'entry::test-1', 'title' => 'Entry 1'], 'text_match' => 12],
],
]);

$results = $index->searchUsingApi('*');

$this->assertSame(['Entry 1'], $results['results']->pluck('title')->all());
}
}
Loading