Skip to content

Commit aded365

Browse files
2 parents f25b2d5 + 2c48119 commit aded365

File tree

6 files changed

+122
-34
lines changed

6 files changed

+122
-34
lines changed

src/momento/internal/aio/_vector_index_data_client.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,19 +98,22 @@ async def upsert_item_batch(
9898
async def delete_item_batch(
9999
self,
100100
index_name: str,
101-
filter: list[str],
101+
filter: FilterExpression | list[str],
102102
) -> DeleteItemBatchResponse:
103103
try:
104104
self._log_issuing_request("DeleteItemBatch", {"index_name": index_name})
105105
_validate_index_name(index_name)
106106

107-
if len(filter) == 0:
108-
return DeleteItemBatch.Success()
107+
filter_expression: vectorindex_pb._FilterExpression
109108

110-
request = vectorindex_pb._DeleteItemBatchRequest(
111-
index_name=index_name,
112-
filter=F.IdInSet(filter).to_filter_expression_proto(),
113-
)
109+
if isinstance(filter, FilterExpression):
110+
filter_expression = filter.to_filter_expression_proto()
111+
else:
112+
if len(filter) == 0:
113+
return DeleteItemBatch.Success()
114+
filter_expression = F.IdInSet(filter).to_filter_expression_proto()
115+
116+
request = vectorindex_pb._DeleteItemBatchRequest(index_name=index_name, filter=filter_expression)
114117

115118
await self._build_stub().DeleteItemBatch(request, timeout=self._default_deadline_seconds)
116119

src/momento/internal/synchronous/_vector_index_data_client.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,19 +98,22 @@ def upsert_item_batch(
9898
def delete_item_batch(
9999
self,
100100
index_name: str,
101-
filter: list[str],
101+
filter: FilterExpression | list[str],
102102
) -> DeleteItemBatchResponse:
103103
try:
104104
self._log_issuing_request("DeleteItemBatch", {"index_name": index_name})
105105
_validate_index_name(index_name)
106106

107-
if len(filter) == 0:
108-
return DeleteItemBatch.Success()
107+
filter_expression: vectorindex_pb._FilterExpression
109108

110-
request = vectorindex_pb._DeleteItemBatchRequest(
111-
index_name=index_name,
112-
filter=F.IdInSet(filter).to_filter_expression_proto(),
113-
)
109+
if isinstance(filter, FilterExpression):
110+
filter_expression = filter.to_filter_expression_proto()
111+
else:
112+
if len(filter) == 0:
113+
return DeleteItemBatch.Success()
114+
filter_expression = F.IdInSet(filter).to_filter_expression_proto()
115+
116+
request = vectorindex_pb._DeleteItemBatchRequest(index_name=index_name, filter=filter_expression)
114117

115118
self._build_stub().DeleteItemBatch(request, timeout=self._default_deadline_seconds)
116119

src/momento/vector_index_client.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,14 +194,16 @@ def upsert_item_batch(self, index_name: str, items: list[Item]) -> UpsertItemBat
194194
"""
195195
return self._data_client.upsert_item_batch(index_name, items)
196196

197-
def delete_item_batch(self, index_name: str, filter: list[str]) -> DeleteItemBatchResponse:
197+
def delete_item_batch(self, index_name: str, filter: FilterExpression | list[str]) -> DeleteItemBatchResponse:
198198
"""Deletes a batch of items from a vector index.
199199
200200
Deletes any and all items with the given IDs from the index.
201201
202202
Args:
203203
index_name (str): Name of the index to delete the items from.
204-
filter (list[str]): The IDs of the items to be deleted from the index.
204+
filter (FilterExpression | list[str]): A filter expression to filter
205+
items by ID. If a list of strings is provided, it is treated as a
206+
"IdInSet" filter expression.
205207
206208
Returns:
207209
DeleteItemBatchResponse: The result of a delete item batch operation.

src/momento/vector_index_client_async.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,14 +194,16 @@ async def upsert_item_batch(self, index_name: str, items: list[Item]) -> UpsertI
194194
"""
195195
return await self._data_client.upsert_item_batch(index_name, items)
196196

197-
async def delete_item_batch(self, index_name: str, filter: list[str]) -> DeleteItemBatchResponse:
197+
async def delete_item_batch(self, index_name: str, filter: FilterExpression | list[str]) -> DeleteItemBatchResponse:
198198
"""Deletes a batch of items from a vector index.
199199
200200
Deletes any and all items with the given IDs from the index.
201201
202202
Args:
203203
index_name (str): Name of the index to delete the items from.
204-
filter (list[str]): The IDs of the items to be deleted from the index.
204+
filter (FilterExpression | list[str]): A filter expression to filter
205+
items by ID. If a list of strings is provided, it is treated as a
206+
"IdInSet" filter expression.
205207
206208
Returns:
207209
DeleteItemBatchResponse: The result of a delete item batch operation.

tests/momento/vector_index_client/test_data.py

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ def test_delete_validates_index_name(vector_index_client: PreviewVectorIndexClie
688688
assert response.error_code == MomentoErrorCode.INVALID_ARGUMENT_ERROR
689689

690690

691-
def test_delete_deletes_ids(
691+
def test_delete_items_by_id(
692692
vector_index_client: PreviewVectorIndexClient,
693693
unique_vector_index_name: TUniqueVectorIndexName,
694694
) -> None:
@@ -701,10 +701,10 @@ def test_delete_deletes_ids(
701701
upsert_response = vector_index_client.upsert_item_batch(
702702
index_name,
703703
items=[
704-
Item(id="test_item_1", vector=[1.0, 2.0]),
705-
Item(id="test_item_2", vector=[3.0, 4.0]),
706-
Item(id="test_item_3", vector=[5.0, 6.0]),
707-
Item(id="test_item_3", vector=[7.0, 8.0]),
704+
Item(id="test_item_1", vector=[1.0, 2.0], metadata={"key": "value1"}),
705+
Item(id="test_item_2", vector=[3.0, 4.0], metadata={"key": "value2"}),
706+
Item(id="test_item_3", vector=[5.0, 6.0], metadata={"key": "value3"}),
707+
Item(id="test_item_4", vector=[7.0, 8.0], metadata={"key": "value4"}),
708708
],
709709
)
710710
assert isinstance(upsert_response, UpsertItemBatch.Success)
@@ -713,10 +713,11 @@ def test_delete_deletes_ids(
713713

714714
search_response = vector_index_client.search(index_name, query_vector=[1.0, 2.0], top_k=10)
715715
assert isinstance(search_response, Search.Success)
716-
assert len(search_response.hits) == 3
716+
assert len(search_response.hits) == 4
717717

718718
assert search_response.hits == [
719-
SearchHit(id="test_item_3", score=23.0),
719+
SearchHit(id="test_item_4", score=23.0),
720+
SearchHit(id="test_item_3", score=17.0),
720721
SearchHit(id="test_item_2", score=11.0),
721722
SearchHit(id="test_item_1", score=5.0),
722723
]
@@ -728,13 +729,50 @@ def test_delete_deletes_ids(
728729

729730
search_response = vector_index_client.search(index_name, query_vector=[1.0, 2.0], top_k=10)
730731
assert isinstance(search_response, Search.Success)
731-
assert len(search_response.hits) == 1
732+
assert len(search_response.hits) == 2
732733

733734
assert search_response.hits == [
735+
SearchHit(id="test_item_4", score=23.0),
734736
SearchHit(id="test_item_2", score=11.0),
735737
]
736738

737739

740+
def test_delete_items_by_filter(
741+
vector_index_client: PreviewVectorIndexClient,
742+
unique_vector_index_name: TUniqueVectorIndexName,
743+
) -> None:
744+
index_name = unique_vector_index_name(vector_index_client)
745+
create_response = vector_index_client.create_index(index_name, num_dimensions=2)
746+
assert isinstance(create_response, CreateIndex.Success)
747+
748+
items = [
749+
Item(id="test_item_1", vector=[1.0, 1.0], metadata={"key": "value1"}),
750+
Item(id="test_item_2", vector=[3.0, 4.0], metadata={"key": "value2"}),
751+
Item(id="test_item_3", vector=[5.0, 6.0], metadata={"key": "value1"}),
752+
Item(id="test_item_4", vector=[7.0, 8.0], metadata={"key": "value2"}),
753+
]
754+
upsert_response = vector_index_client.upsert_item_batch(
755+
index_name,
756+
items=items,
757+
)
758+
assert isinstance(upsert_response, UpsertItemBatch.Success)
759+
760+
sleep(2)
761+
762+
search_response = vector_index_client.search(index_name, query_vector=[1.0, 1.0], top_k=10)
763+
assert isinstance(search_response, Search.Success)
764+
assert len(search_response.hits) == 4
765+
766+
delete_response = vector_index_client.delete_item_batch(index_name, filter=filters.Equals("key", "value1"))
767+
assert isinstance(delete_response, DeleteItemBatch.Success)
768+
769+
sleep(2)
770+
771+
search_response = vector_index_client.search(index_name, query_vector=[1.0, 1.0], top_k=10)
772+
assert isinstance(search_response, Search.Success)
773+
assert len(search_response.hits) == 2
774+
775+
738776
@pytest.mark.parametrize(
739777
[
740778
"get_item_method_name",

tests/momento/vector_index_client/test_data_async.py

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -692,7 +692,7 @@ async def test_delete_validates_index_name(vector_index_client_async: PreviewVec
692692
assert response.error_code == MomentoErrorCode.INVALID_ARGUMENT_ERROR
693693

694694

695-
async def test_delete_deletes_ids(
695+
async def test_delete_items_by_id(
696696
vector_index_client_async: PreviewVectorIndexClientAsync,
697697
unique_vector_index_name_async: TUniqueVectorIndexNameAsync,
698698
) -> None:
@@ -705,10 +705,10 @@ async def test_delete_deletes_ids(
705705
upsert_response = await vector_index_client_async.upsert_item_batch(
706706
index_name,
707707
items=[
708-
Item(id="test_item_1", vector=[1.0, 2.0]),
709-
Item(id="test_item_2", vector=[3.0, 4.0]),
710-
Item(id="test_item_3", vector=[5.0, 6.0]),
711-
Item(id="test_item_3", vector=[7.0, 8.0]),
708+
Item(id="test_item_1", vector=[1.0, 2.0], metadata={"key": "value1"}),
709+
Item(id="test_item_2", vector=[3.0, 4.0], metadata={"key": "value2"}),
710+
Item(id="test_item_3", vector=[5.0, 6.0], metadata={"key": "value3"}),
711+
Item(id="test_item_4", vector=[7.0, 8.0], metadata={"key": "value4"}),
712712
],
713713
)
714714
assert isinstance(upsert_response, UpsertItemBatch.Success)
@@ -717,10 +717,11 @@ async def test_delete_deletes_ids(
717717

718718
search_response = await vector_index_client_async.search(index_name, query_vector=[1.0, 2.0], top_k=10)
719719
assert isinstance(search_response, Search.Success)
720-
assert len(search_response.hits) == 3
720+
assert len(search_response.hits) == 4
721721

722722
assert search_response.hits == [
723-
SearchHit(id="test_item_3", score=23.0),
723+
SearchHit(id="test_item_4", score=23.0),
724+
SearchHit(id="test_item_3", score=17.0),
724725
SearchHit(id="test_item_2", score=11.0),
725726
SearchHit(id="test_item_1", score=5.0),
726727
]
@@ -734,13 +735,52 @@ async def test_delete_deletes_ids(
734735

735736
search_response = await vector_index_client_async.search(index_name, query_vector=[1.0, 2.0], top_k=10)
736737
assert isinstance(search_response, Search.Success)
737-
assert len(search_response.hits) == 1
738+
assert len(search_response.hits) == 2
738739

739740
assert search_response.hits == [
741+
SearchHit(id="test_item_4", score=23.0),
740742
SearchHit(id="test_item_2", score=11.0),
741743
]
742744

743745

746+
async def test_delete_items_by_filter(
747+
vector_index_client_async: PreviewVectorIndexClientAsync,
748+
unique_vector_index_name_async: TUniqueVectorIndexNameAsync,
749+
) -> None:
750+
index_name = unique_vector_index_name_async(vector_index_client_async)
751+
create_response = await vector_index_client_async.create_index(index_name, num_dimensions=2)
752+
assert isinstance(create_response, CreateIndex.Success)
753+
754+
items = [
755+
Item(id="test_item_1", vector=[1.0, 1.0], metadata={"key": "value1"}),
756+
Item(id="test_item_2", vector=[3.0, 4.0], metadata={"key": "value2"}),
757+
Item(id="test_item_3", vector=[5.0, 6.0], metadata={"key": "value1"}),
758+
Item(id="test_item_4", vector=[7.0, 8.0], metadata={"key": "value2"}),
759+
]
760+
upsert_response = await vector_index_client_async.upsert_item_batch(
761+
index_name,
762+
items=items,
763+
)
764+
assert isinstance(upsert_response, UpsertItemBatch.Success)
765+
766+
await sleep_async(2)
767+
768+
search_response = await vector_index_client_async.search(index_name, query_vector=[1.0, 1.0], top_k=10)
769+
assert isinstance(search_response, Search.Success)
770+
assert len(search_response.hits) == 4
771+
772+
delete_response = await vector_index_client_async.delete_item_batch(
773+
index_name, filter=filters.Equals("key", "value1")
774+
)
775+
assert isinstance(delete_response, DeleteItemBatch.Success)
776+
777+
await sleep_async(2)
778+
779+
search_response = await vector_index_client_async.search(index_name, query_vector=[1.0, 1.0], top_k=10)
780+
assert isinstance(search_response, Search.Success)
781+
assert len(search_response.hits) == 2
782+
783+
744784
@pytest.mark.parametrize(
745785
[
746786
"get_item_method_name",

0 commit comments

Comments
 (0)