How to delete documents from a Haystack document store

Search indexes keep returning obsolete or sensitive records until their document IDs are removed. A safe deletion identifies the exact records first and proves that unrelated stored content remains directly enumerable afterward.

The common Haystack DocumentStore protocol accepts a list of IDs through delete_documents(). The method does not return a deletion count, so the code checks that every requested ID exists before the destructive call and compares the remaining IDs with an expected set afterward.

An InMemoryDocumentStore keeps the demonstration temporary and requires no external service. Integrations backed by persistent indexes apply the same deletion to durable data, which makes a source copy or re-indexing path essential when the records may need to be restored.

Steps to delete documents from a Haystack document store:

  1. Create document_store_delete_demo.py with the Document import and an empty InMemoryDocumentStore.
    document_store_delete_demo.py
    from haystack import Document
    from haystack.document_stores.in_memory import InMemoryDocumentStore
     
     
    document_store = InMemoryDocumentStore()

    The Python environment needs the haystack-ai package.
    Related: How to install Haystack with pip

  2. Add three sample documents below the store assignment with explicit IDs for the deletion boundary.
    document_store_delete_demo.py
    documents = [
        Document(
            id="policy-public-v1",
            content="Publish the customer support escalation policy.",
        ),
        Document(
            id="policy-private-v1",
            content="Remove the internal salary review notes from search.",
        ),
        Document(
            id="policy-retired-v1",
            content="Retire the old refund policy from the help center index.",
        ),
    ]
  3. Write the sample documents to the in-memory store.
    document_store_delete_demo.py
    document_store.write_documents(documents)
  4. Add a pre-deletion guard below write_documents() for missing requested IDs.
    document_store_delete_demo.py
    delete_ids = ["policy-private-v1", "policy-retired-v1"]
    before_ids = {document.id for document in document_store.filter_documents()}
    missing_ids = set(delete_ids) - before_ids
     
    if missing_ids:
        raise RuntimeError(f"requested IDs were not found: {sorted(missing_ids)}")
     
    print(f"delete ids: {delete_ids}")
  5. Delete the two reviewed document IDs with delete_documents().

    A persistent document store removes these records from its durable index, and recovery requires the original source documents or another re-indexing path.

    document_store_delete_demo.py
    document_store.delete_documents(document_ids=delete_ids)
  6. Add an after-state assertion below the deletion call for the one retained document.
    document_store_delete_demo.py
    remaining_ids = {document.id for document in document_store.filter_documents()}
    expected_ids = {"policy-public-v1"}
     
    if remaining_ids != expected_ids:
        raise RuntimeError(
            f"unexpected remaining IDs: expected {sorted(expected_ids)}, "
            f"got {sorted(remaining_ids)}"
        )
     
    print(f"remaining ids: {sorted(remaining_ids)}")
  7. Compare document_store_delete_demo.py with the completed program after constructing each section.
    document_store_delete_demo.py
    from haystack import Document
    from haystack.document_stores.in_memory import InMemoryDocumentStore
     
     
    document_store = InMemoryDocumentStore()
     
    documents = [
        Document(
            id="policy-public-v1",
            content="Publish the customer support escalation policy.",
        ),
        Document(
            id="policy-private-v1",
            content="Remove the internal salary review notes from search.",
        ),
        Document(
            id="policy-retired-v1",
            content="Retire the old refund policy from the help center index.",
        ),
    ]
     
    document_store.write_documents(documents)
     
    delete_ids = ["policy-private-v1", "policy-retired-v1"]
    before_ids = {document.id for document in document_store.filter_documents()}
    missing_ids = set(delete_ids) - before_ids
     
    if missing_ids:
        raise RuntimeError(f"requested IDs were not found: {sorted(missing_ids)}")
     
    print(f"delete ids: {delete_ids}")
     
    document_store.delete_documents(document_ids=delete_ids)
     
    remaining_ids = {document.id for document in document_store.filter_documents()}
    expected_ids = {"policy-public-v1"}
     
    if remaining_ids != expected_ids:
        raise RuntimeError(
            f"unexpected remaining IDs: expected {sorted(expected_ids)}, "
            f"got {sorted(remaining_ids)}"
        )
     
    print(f"remaining ids: {sorted(remaining_ids)}")
  8. Verify the deletion by running the completed program.
    $ python3 document_store_delete_demo.py
    delete ids: ['policy-private-v1', 'policy-retired-v1']
    remaining ids: ['policy-public-v1']

    The final list excludes both requested IDs and retains policy-public-v1. The program raises RuntimeError instead when a requested ID is missing before deletion or the remaining set differs from the expected set.