Skip to content

Commit 8ea9920

Browse files
committed
count number of docs between deleted operation and return the difference after delete operation
1 parent d87afdc commit 8ea9920

3 files changed

Lines changed: 53 additions & 20 deletions

File tree

integrations/qdrant/src/haystack_integrations/document_stores/qdrant/document_store.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ async def delete_documents_async(self, document_ids: list[str]) -> None:
517517
"Called QdrantDocumentStore.delete_documents_async() on a non-existing ID",
518518
)
519519

520-
def delete_by_filter(self, filters: dict[str, Any]) -> None:
520+
def delete_by_filter(self, filters: dict[str, Any]) -> int:
521521
"""
522522
Deletes all documents that match the provided filters.
523523
@@ -533,20 +533,26 @@ def delete_by_filter(self, filters: dict[str, Any]) -> None:
533533
try:
534534
qdrant_filter = convert_filters_to_qdrant(filters)
535535
if qdrant_filter is None:
536-
return
536+
return 0
537+
538+
count_response = self._client.count(
539+
collection_name=self.index,
540+
count_filter=qdrant_filter,
541+
)
542+
deleted_count = count_response.count
537543

538-
# perform deletion using FilterSelector
539544
self._client.delete(
540545
collection_name=self.index,
541546
points_selector=rest.FilterSelector(filter=qdrant_filter),
542547
wait=self.wait_result_from_api,
543548
)
549+
return deleted_count
544550

545551
except Exception as e:
546552
msg = f"Failed to delete documents by filter from Qdrant: {e!s}"
547553
raise QdrantStoreError(msg) from e
548554

549-
async def delete_by_filter_async(self, filters: dict[str, Any]) -> None:
555+
async def delete_by_filter_async(self, filters: dict[str, Any]) -> int:
550556
"""
551557
Asynchronously deletes all documents that match the provided filters.
552558
@@ -562,14 +568,20 @@ async def delete_by_filter_async(self, filters: dict[str, Any]) -> None:
562568
try:
563569
qdrant_filter = convert_filters_to_qdrant(filters)
564570
if qdrant_filter is None:
565-
return
571+
return 0
572+
573+
count_response = await self._async_client.count(
574+
collection_name=self.index,
575+
count_filter=qdrant_filter,
576+
)
577+
deleted_count = count_response.count
566578

567-
# perform deletion using FilterSelector
568579
await self._async_client.delete(
569580
collection_name=self.index,
570581
points_selector=rest.FilterSelector(filter=qdrant_filter),
571582
wait=self.wait_result_from_api,
572583
)
584+
return deleted_count
573585

574586
except Exception as e:
575587
msg = f"Failed to delete documents by filter from Qdrant: {e!s}"

integrations/qdrant/tests/test_document_store.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -348,15 +348,20 @@ def test_delete_by_filter(self, document_store: QdrantDocumentStore):
348348
]
349349
document_store.write_documents(docs)
350350
assert document_store.count_documents() == 3
351-
document_store.delete_by_filter(filters={"field": "meta.category", "operator": "==", "value": "A"})
351+
352+
deleted_count = document_store.delete_by_filter(
353+
filters={"field": "meta.category", "operator": "==", "value": "A"}
354+
)
355+
assert deleted_count == 2
352356

353357
# Verify only category B remains
354358
remaining_docs = document_store.filter_documents()
355359
assert len(remaining_docs) == 1
356360
assert remaining_docs[0].meta["category"] == "B"
357361

358362
# Delete remaining document by year
359-
document_store.delete_by_filter(filters={"field": "meta.year", "operator": "==", "value": 2023})
363+
deleted_count = document_store.delete_by_filter(filters={"field": "meta.year", "operator": "==", "value": 2023})
364+
assert deleted_count == 1
360365
assert document_store.count_documents() == 0
361366

362367
def test_delete_by_filter_no_matches(self, document_store: QdrantDocumentStore):
@@ -368,7 +373,10 @@ def test_delete_by_filter_no_matches(self, document_store: QdrantDocumentStore):
368373
assert document_store.count_documents() == 2
369374

370375
# try to delete documents with category="C" (no matches)
371-
document_store.delete_by_filter(filters={"field": "meta.category", "operator": "==", "value": "C"})
376+
deleted_count = document_store.delete_by_filter(
377+
filters={"field": "meta.category", "operator": "==", "value": "C"}
378+
)
379+
assert deleted_count == 0
372380
assert document_store.count_documents() == 2
373381

374382
def test_delete_by_filter_advanced_filters(self, document_store: QdrantDocumentStore):
@@ -380,8 +388,8 @@ def test_delete_by_filter_advanced_filters(self, document_store: QdrantDocumentS
380388
document_store.write_documents(docs)
381389
assert document_store.count_documents() == 3
382390

383-
# AND condition
384-
document_store.delete_by_filter(
391+
# AND condition (matches only Doc 1)
392+
deleted_count = document_store.delete_by_filter(
385393
filters={
386394
"operator": "AND",
387395
"conditions": [
@@ -390,10 +398,11 @@ def test_delete_by_filter_advanced_filters(self, document_store: QdrantDocumentS
390398
],
391399
}
392400
)
401+
assert deleted_count == 1
393402
assert document_store.count_documents() == 2
394403

395-
# OR condition
396-
document_store.delete_by_filter(
404+
# OR condition (matches Doc 2 and Doc 3)
405+
deleted_count = document_store.delete_by_filter(
397406
filters={
398407
"operator": "OR",
399408
"conditions": [
@@ -402,6 +411,7 @@ def test_delete_by_filter_advanced_filters(self, document_store: QdrantDocumentS
402411
],
403412
}
404413
)
414+
assert deleted_count == 2
405415
assert document_store.count_documents() == 0
406416

407417
def test_update_by_filter(self, document_store: QdrantDocumentStore):

integrations/qdrant/tests/test_document_store_async.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,10 @@ async def test_delete_by_filter_async(self, document_store: QdrantDocumentStore)
275275
assert await document_store.count_documents_async() == 3
276276

277277
# Delete documents with category="A"
278-
await document_store.delete_by_filter_async(filters={"field": "meta.category", "operator": "==", "value": "A"})
278+
deleted_count = await document_store.delete_by_filter_async(
279+
filters={"field": "meta.category", "operator": "==", "value": "A"}
280+
)
281+
assert deleted_count == 2
279282
assert await document_store.count_documents_async() == 1
280283

281284
# Verify only category B remains
@@ -286,7 +289,10 @@ async def test_delete_by_filter_async(self, document_store: QdrantDocumentStore)
286289
assert remaining_docs[0].meta["category"] == "B"
287290

288291
# Delete remaining document by year
289-
await document_store.delete_by_filter_async(filters={"field": "meta.year", "operator": "==", "value": 2023})
292+
deleted_count = await document_store.delete_by_filter_async(
293+
filters={"field": "meta.year", "operator": "==", "value": 2023}
294+
)
295+
assert deleted_count == 1
290296
assert await document_store.count_documents_async() == 0
291297

292298
@pytest.mark.asyncio
@@ -299,7 +305,10 @@ async def test_delete_by_filter_async_no_matches(self, document_store: QdrantDoc
299305
assert await document_store.count_documents_async() == 2
300306

301307
# Try to delete documents with category="C" (no matches)
302-
await document_store.delete_by_filter_async(filters={"field": "meta.category", "operator": "==", "value": "C"})
308+
deleted_count = await document_store.delete_by_filter_async(
309+
filters={"field": "meta.category", "operator": "==", "value": "C"}
310+
)
311+
assert deleted_count == 0
303312
assert await document_store.count_documents_async() == 2
304313

305314
@pytest.mark.asyncio
@@ -312,8 +321,8 @@ async def test_delete_by_filter_async_advanced_filters(self, document_store: Qdr
312321
await document_store.write_documents_async(docs)
313322
assert await document_store.count_documents_async() == 3
314323

315-
# AND condition
316-
await document_store.delete_by_filter_async(
324+
# AND condition (matches only Doc 1)
325+
deleted_count = await document_store.delete_by_filter_async(
317326
filters={
318327
"operator": "AND",
319328
"conditions": [
@@ -322,10 +331,11 @@ async def test_delete_by_filter_async_advanced_filters(self, document_store: Qdr
322331
],
323332
}
324333
)
334+
assert deleted_count == 1
325335
assert await document_store.count_documents_async() == 2
326336

327-
# OR condition
328-
await document_store.delete_by_filter_async(
337+
# OR condition (matches Doc 2 and Doc 3)
338+
deleted_count = await document_store.delete_by_filter_async(
329339
filters={
330340
"operator": "OR",
331341
"conditions": [
@@ -334,6 +344,7 @@ async def test_delete_by_filter_async_advanced_filters(self, document_store: Qdr
334344
],
335345
}
336346
)
347+
assert deleted_count == 2
337348
assert await document_store.count_documents_async() == 0
338349

339350
@pytest.mark.asyncio

0 commit comments

Comments
 (0)