Skip to content

Commit 9423770

Browse files
committed
feat: delete vectors with metadata filter and id prefix
1 parent b899b20 commit 9423770

File tree

6 files changed

+109
-20
lines changed

6 files changed

+109
-20
lines changed

src/Contracts/IndexNamespaceInterface.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,8 @@ public function update(VectorUpdate $update): void;
6464
public function range(VectorRange $range): VectorRangeResult;
6565

6666
public function rangeIterator(VectorRange $range): VectorRangeIterator;
67+
68+
public function deleteUsingIdPrefix(string $prefix): VectorDeleteResult;
69+
70+
public function deleteUsingMetadataFilter(string $filter): VectorDeleteResult;
6771
}

src/Index.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,14 @@ public function rangeIterator(VectorRange $range): VectorRangeIterator
152152
{
153153
return $this->namespace('')->rangeIterator($range);
154154
}
155+
156+
public function deleteUsingIdPrefix(string $prefix): VectorDeleteResult
157+
{
158+
return $this->namespace('')->deleteUsingIdPrefix($prefix);
159+
}
160+
161+
public function deleteUsingMetadataFilter(string $filter): VectorDeleteResult
162+
{
163+
return $this->namespace('')->deleteUsingMetadataFilter($filter);
164+
}
155165
}

src/IndexNamespace.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,14 @@ public function rangeIterator(VectorRange $range): VectorRangeIterator
104104
{
105105
return (new RangeVectorsOperation($this->namespace, $this->transporter))->rangeIterator($range);
106106
}
107+
108+
public function deleteUsingIdPrefix(string $prefix): VectorDeleteResult
109+
{
110+
return (new DeleteVectorsOperation($this->namespace, $this->transporter))->deleteUsingIdPrefix($prefix);
111+
}
112+
113+
public function deleteUsingMetadataFilter(string $filter): VectorDeleteResult
114+
{
115+
return (new DeleteVectorsOperation($this->namespace, $this->transporter))->deleteUsingMetadataFilter($filter);
116+
}
107117
}

src/Operations/DeleteVectorsOperation.php

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,42 @@ public function __construct(private string $namespace, private TransporterInterf
2727
*/
2828
public function delete(array $ids): VectorDeleteResult
2929
{
30-
$path = $this->getPath();
31-
$vectorIds = $this->mapIds($ids);
30+
return $this->sendDeleteRequest([
31+
'ids' => $this->mapIds($ids),
32+
]);
33+
}
34+
35+
public function deleteUsingIdPrefix(string $prefix): VectorDeleteResult
36+
{
37+
return $this->sendDeleteRequest(compact('prefix'));
38+
}
39+
40+
public function deleteUsingMetadataFilter(string $filter): VectorDeleteResult
41+
{
42+
return $this->sendDeleteRequest(compact('filter'));
43+
}
44+
45+
private function getPath(): string
46+
{
47+
$namespace = trim($this->namespace);
48+
if ($namespace === '') {
49+
return '/delete';
50+
}
51+
52+
return "/delete/$namespace";
53+
}
3254

55+
/**
56+
* @param array<string, mixed> $payload
57+
*/
58+
private function sendDeleteRequest(array $payload): VectorDeleteResult
59+
{
3360
try {
3461
$request = new TransporterRequest(
3562
contentType: ContentType::JSON,
3663
method: Method::DELETE,
37-
path: $path,
38-
data: $vectorIds,
64+
path: $this->getPath(),
65+
data: $payload,
3966
);
4067
} catch (\JsonException $e) {
4168
throw new OperationFailedException('Invalid JSON');
@@ -48,16 +75,6 @@ public function delete(array $ids): VectorDeleteResult
4875
return $this->transformResponse($response);
4976
}
5077

51-
private function getPath(): string
52-
{
53-
$namespace = trim($this->namespace);
54-
if ($namespace === '') {
55-
return '/delete';
56-
}
57-
58-
return "/delete/$namespace";
59-
}
60-
6178
private function transformResponse(TransporterResponse $response): VectorDeleteResult
6279
{
6380
$data = json_decode($response->data, true)['result'] ?? [];

src/Transporter/Headers.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
/**
66
* @internal
77
*/
8-
class Headers
8+
readonly class Headers
99
{
1010
/**
1111
* @param array<string, string> $headers

tests/Dense/Operations/DeleteVectorsOperationTest.php

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ class DeleteVectorsOperationTest extends TestCase
1818
public function test_delete_vectors(): void
1919
{
2020
$this->namespace->upsertMany([
21-
new VectorUpsert('id-1', createRandomVector(2)),
22-
new VectorUpsert('id-2', createRandomVector(2)),
23-
new VectorUpsert('id-3', createRandomVector(2)),
21+
new VectorUpsert('id-1', vector: createRandomVector(2)),
22+
new VectorUpsert('id-2', vector: createRandomVector(2)),
23+
new VectorUpsert('id-3', vector: createRandomVector(2)),
2424
]);
2525
$this->waitForIndex($this->namespace);
2626

@@ -39,8 +39,8 @@ public function test_delete_vectors_from_a_query_result_results(): void
3939
$vector = createRandomVector(2);
4040
$this->namespace->upsertMany([
4141
new VectorUpsert('id-1', $vector),
42-
new VectorUpsert('id-2', createRandomVector(2)),
43-
new VectorUpsert('id-3', createRandomVector(2)),
42+
new VectorUpsert('id-2', vector: createRandomVector(2)),
43+
new VectorUpsert('id-3', vector: createRandomVector(2)),
4444
]);
4545
$this->waitForIndex($this->namespace);
4646

@@ -53,4 +53,52 @@ public function test_delete_vectors_from_a_query_result_results(): void
5353

5454
$this->assertEquals(2, $result->deleted);
5555
}
56+
57+
public function test_delete_vectors_using_an_id_prefix(): void
58+
{
59+
$this->namespace->upsertMany([
60+
new VectorUpsert('users:1', vector: createRandomVector(2)),
61+
new VectorUpsert('users:2', vector: createRandomVector(2)),
62+
new VectorUpsert('posts:1', vector: createRandomVector(2)),
63+
]);
64+
$this->waitForIndex($this->namespace);
65+
66+
$result = $this->namespace->deleteUsingIdPrefix('users:*');
67+
68+
$this->assertEquals(2, $result->deleted);
69+
$this->assertEquals(1, $this->namespace->getNamespaceInfo()->vectorCount);
70+
}
71+
72+
public function test_delete_vectors_using_a_metadata_filter(): void
73+
{
74+
$this->namespace->upsertMany([
75+
new VectorUpsert(
76+
id: 'users:1',
77+
vector: createRandomVector(2),
78+
metadata: [
79+
'salary' => 1000,
80+
],
81+
),
82+
new VectorUpsert(
83+
id: 'users:2',
84+
vector: createRandomVector(2),
85+
metadata: [
86+
'salary' => 2000,
87+
],
88+
),
89+
new VectorUpsert(
90+
id: 'users:3',
91+
vector: createRandomVector(2),
92+
metadata: [
93+
'salary' => 3000,
94+
],
95+
),
96+
]);
97+
$this->waitForIndex($this->namespace);
98+
99+
$result = $this->namespace->deleteUsingMetadataFilter('salary < 3000');
100+
101+
$this->assertEquals(2, $result->deleted);
102+
$this->assertEquals(1, $this->namespace->getNamespaceInfo()->vectorCount);
103+
}
56104
}

0 commit comments

Comments
 (0)