Skip to content

Commit c757b9c

Browse files
committed
feat: add ability to access fetched vectors by their id
1 parent a4b496f commit c757b9c

File tree

3 files changed

+59
-5
lines changed

3 files changed

+59
-5
lines changed

src/Operations/FetchVectorsOperation.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Upstash\Vector\Transporter\TransporterResponse;
1212
use Upstash\Vector\VectorFetch;
1313
use Upstash\Vector\VectorFetchResult;
14+
use Upstash\Vector\VectorMatch;
1415

1516
/**
1617
* @internal
@@ -58,7 +59,11 @@ private function transformResponse(TransporterResponse $response): VectorFetchRe
5859
$result = array_filter($result);
5960

6061
$results = array_map(fn (array $result) => $this->mapVectorMatch($result), $result);
62+
$keys = array_map(fn (VectorMatch $match) => $match->getIdentifier(), $results);
6163

62-
return new VectorFetchResult($results);
64+
// Key-by vector ID
65+
$results = array_combine($keys, $results);
66+
67+
return new VectorFetchResult($keys, $results);
6368
}
6469
}

src/VectorFetchResult.php

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,38 @@
1010

1111
/**
1212
* @implements IteratorAggregate<int,VectorMatch>
13-
* @implements ArrayAccess<int,VectorMatch>
13+
* @implements ArrayAccess<int,VectorMatch|null>
1414
*/
1515
final readonly class VectorFetchResult implements ArrayAccess, Countable, IteratorAggregate
1616
{
1717
/**
1818
* @param array<VectorMatch> $results
1919
*/
2020
public function __construct(
21+
private array $keys,
2122
public array $results,
2223
) {}
2324

2425
public function offsetExists(mixed $offset): bool
2526
{
27+
if (is_int($offset)) {
28+
$offset = $this->keys[$offset] ?? $offset;
29+
}
30+
2631
return isset($this->results[$offset]);
2732
}
2833

29-
public function offsetGet(mixed $offset): VectorMatch
34+
public function offsetGet(mixed $offset): ?VectorMatch
3035
{
31-
return $this->results[$offset];
36+
if (is_int($offset)) {
37+
$offset = $this->keys[$offset] ?? $offset;
38+
}
39+
40+
if ($this->offsetExists($offset)) {
41+
return $this->results[$offset];
42+
}
43+
44+
return null;
3245
}
3346

3447
public function offsetSet(mixed $offset, mixed $value): void {}

tests/Dense/Operations/FetchVectorsOperationTest.php

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,30 @@ public function test_can_fetch_vectors(): void
3333

3434
// Assert
3535
$this->assertCount(2, $results);
36-
$this->assertCount(2, $results[0]->vector);
36+
$this->assertNotNull($results[0]->vector);
37+
$this->assertCount(2, $results[0]->vector); // O(n)
38+
}
39+
40+
public function test_can_fetch_vectors_and_reference_them_by_vector_id(): void
41+
{
42+
// Arrange
43+
$this->namespace->upsertMany([
44+
new VectorUpsert(id: '1', vector: createRandomVector(2)),
45+
new VectorUpsert(id: '2', vector: createRandomVector(2)),
46+
new VectorUpsert(id: '3', vector: createRandomVector(2)),
47+
]);
48+
$this->waitForIndex($this->namespace);
49+
50+
// Act
51+
$results = $this->namespace->fetch(new VectorFetch(
52+
ids: ['1', '2'],
53+
includeVectors: true,
54+
));
55+
56+
// Assert
57+
$this->assertCount(2, $results);
58+
$this->assertNotNull($results['1']->vector);
59+
$this->assertCount(2, $results['1']->vector); // O(n)
3760
}
3861

3962
public function test_can_fetch_vectors_that_dont_exist(): void
@@ -47,4 +70,17 @@ public function test_can_fetch_vectors_that_dont_exist(): void
4770
// Assert
4871
$this->assertCount(0, $results);
4972
}
73+
74+
public function test_can_fetch_vectors_that_dont_exist_and_get_null(): void
75+
{
76+
// Act
77+
$results = $this->namespace->fetch(new VectorFetch(
78+
ids: ['1', '2'],
79+
includeVectors: true,
80+
));
81+
82+
// Assert
83+
$this->assertNull($results[0]);
84+
$this->assertNull($results['1']);
85+
}
5086
}

0 commit comments

Comments
 (0)