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
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ jobs:
composer update --prefer-dist --no-interaction --no-progress

- name: Execute tests
run: vendor/bin/phpunit --display-deprecations --fail-on-deprecation
run: vendor/bin/phpunit --display-deprecations
42 changes: 40 additions & 2 deletions src/Drivers/RedisDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,40 @@ public function search(string $modelClass, string $attribute, array $queryVector
{
$this->ensureIndex(count($queryVector));

try {
$result = $this->runSearch($modelClass, $attribute, $queryVector, $limit);
} catch (ServerException $e) {
if (!$this->isMissingIndex($e)) {
throw $e;
}

self::$indexEnsured = false;
$this->ensureIndex(count($queryVector));
$result = $this->runSearch($modelClass, $attribute, $queryVector, $limit);
}

return $this->parseSearchResults($result);
}

/**
* Issue the actual FT.SEARCH KNN query and return its raw reply.
*
* @param string $modelClass
* @param string $attribute
* @param array<int, float> $queryVector
* @param int $limit
* @return array<int, mixed>
*/
private function runSearch(string $modelClass, string $attribute, array $queryVector, int $limit): array
{
$query = sprintf(
'(@embeddable_type:{%s} @attribute:{%s})=>[KNN %d @vector $vec AS score]',
$this->escapeTag($modelClass),
$this->escapeTag($attribute),
$limit,
);

$result = $this->client->executeCommand(RawCommand::create(
return $this->client->executeCommand(RawCommand::create(
'FT.SEARCH',
self::INDEX_NAME,
$query,
Expand All @@ -129,8 +155,20 @@ public function search(string $modelClass, string $attribute, array $queryVector
'DIALECT',
'2',
));
}

return $this->parseSearchResults($result);
/**
* Whether a ServerException from Redis represents a missing index
* (as opposed to some other command failure that should propagate).
*
* @param ServerException $e
* @return bool
*/
private function isMissingIndex(ServerException $e): bool
{
$message = strtolower($e->getMessage());

return str_contains($message, 'no such index') || str_contains($message, 'unknown index name');
}

/**
Expand Down
Loading