Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
9d8e86c
removing test_delete_all_documents from PgVector - already in haystac…
davidsbatista Jan 30, 2026
209fbd4
removing duplicated tests from OpenSearchDocumentStore
davidsbatista Jan 30, 2026
67691fc
removing duplicated tests from ElasticStoreDocumentTest
davidsbatista Jan 30, 2026
b44db88
Merge branch 'main' into chore/removing-duplicated-standardised-tests
davidsbatista Feb 3, 2026
ac86e25
removing test_delete_all_documents from weaviate
davidsbatista Feb 3, 2026
f988689
removing test_delete_all_documents from qdrant
davidsbatista Feb 3, 2026
db69880
removing delete_all_documents tests from PineCone
davidsbatista Feb 3, 2026
aafc759
removing delete_all_documents tests from MondoDBDocumentStore
davidsbatista Feb 3, 2026
4d26424
adding check for empty list for delete_all_documents on Chroma
davidsbatista Feb 3, 2026
fa8543d
removing delete_all_documents tests from AzureAISearchDocumentStore
davidsbatista Feb 3, 2026
f942fb6
fixing Pinecone tests
davidsbatista Feb 3, 2026
5e1bc28
cleaning up tests in qdrant and weaviate
davidsbatista Feb 3, 2026
9b8d9ed
removing more weavite delete_by_filter tests
davidsbatista Feb 3, 2026
a81ebe1
cleaning up tests in pgvector
davidsbatista Feb 3, 2026
5e5094c
updating OpenSearch: delete_by_filter_async refresh=True as default
davidsbatista Feb 3, 2026
7f0e42f
updating OpenSearch: update_by_filter refresh=True as default
davidsbatista Feb 4, 2026
c255ace
removing standard test from MongoDBDocumentStore
davidsbatista Feb 4, 2026
ffa3de2
reverting default refresh param in OpenSearch
davidsbatista Feb 4, 2026
8aa003b
removing standard test from Chroma
davidsbatista Feb 4, 2026
6755b5c
updating AzuresAISearchDocumentStore to make use of base tests
davidsbatista Feb 4, 2026
f91e400
removing duplicated tests from Astra
davidsbatista Feb 4, 2026
7ed085f
adding UpdateByFilterTest to Weavite
davidsbatista Feb 4, 2026
46a529a
Merge branch 'main' into chore/removing-duplicated-standardised-tests
davidsbatista Feb 4, 2026
76ae193
fixing Azure linting issues
davidsbatista Feb 4, 2026
64025a0
formatting
davidsbatista Feb 4, 2026
aebfed7
formatting
davidsbatista Feb 4, 2026
c52bd30
temporarly using haystack branch with new standard tests
davidsbatista Feb 4, 2026
cfcb9d9
temporarly using haystack branch with new standard tests
davidsbatista Feb 4, 2026
6be83a1
formatting
davidsbatista Feb 4, 2026
4ef9058
removing duplicated tests from Pinecone
davidsbatista Feb 4, 2026
3c56a05
updating all tests to use new test class from haystack core
davidsbatista Feb 5, 2026
8621761
fixing imports for 3.10
davidsbatista Feb 5, 2026
1413474
Merge branch 'main' into chore/removing-duplicated-standardised-tests
davidsbatista Feb 5, 2026
51c5f24
fixing linting issues
davidsbatista Feb 5, 2026
1076980
fixing azure_ai_search overrides due to class changes in haystack core
davidsbatista Feb 5, 2026
06dfe54
fixing linting
davidsbatista Feb 5, 2026
5bb97bc
Merge branch 'main' into chore/removing-duplicated-standardised-tests
davidsbatista Feb 5, 2026
0c55060
chaning imports due to MRO errors + changing document_stores fixtures…
davidsbatista Feb 5, 2026
607b561
fixing weaviate tests and imports
davidsbatista Feb 5, 2026
abc2cc9
fixing Qdrandt tests and imports
davidsbatista Feb 5, 2026
db06bfe
fixing PGVector tests
davidsbatista Feb 5, 2026
55ddf42
fixing Chroma tests + imports
davidsbatista Feb 5, 2026
e858ad0
pointing all pyproject.toml to main
davidsbatista Feb 5, 2026
f20f193
fixing elasticsearch 3.10 arg not used
davidsbatista Feb 5, 2026
720deb4
fixing mongodb imports
davidsbatista Feb 5, 2026
e16a772
fixing chroma formatting
davidsbatista Feb 5, 2026
2ba39f7
fixing weaviate tests and imports
davidsbatista Feb 5, 2026
be16e20
fixing pinecone imports
davidsbatista Feb 5, 2026
cc54b45
attending PR comments
davidsbatista Feb 5, 2026
f8f9380
removing white space
davidsbatista Feb 5, 2026
4dd4527
adding filterable docs fixture to azure_ai_search
davidsbatista Feb 5, 2026
8973ee0
fixing linter
davidsbatista Feb 5, 2026
94e8d0a
Merge branch 'main' into chore/removing-duplicated-standardised-tests
davidsbatista Feb 11, 2026
c9a7dd7
Merge branch 'main' into chore/removing-duplicated-standardised-tests
davidsbatista Feb 12, 2026
8e81355
updating pyproject.toml to reference pypi instead of main branch
davidsbatista Feb 12, 2026
45e7670
updating pyproject.toml to reference latest pypi instead of main branch
davidsbatista Feb 12, 2026
5801389
Update integrations/qdrant/pyproject.toml
davidsbatista Feb 12, 2026
09112af
Update integrations/pgvector/pyproject.toml
davidsbatista Feb 12, 2026
35f1c12
Update integrations/mongodb_atlas/pyproject.toml
davidsbatista Feb 12, 2026
ef0fec0
Update integrations/weaviate/pyproject.toml
davidsbatista Feb 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion integrations/astra/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ classifiers = [
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
]
dependencies = ["haystack-ai>=2.22.0", "pydantic", "typing_extensions", "astrapy>=1.5.0,<2.0"]
dependencies = [
"astrapy>=1.5.0,<2.0",
"haystack-ai>=2.24.0",
"pydantic",
"typing_extensions",
]

[project.urls]
Documentation = "https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/astra#readme"
Expand Down
74 changes: 3 additions & 71 deletions integrations/astra/tests/test_document_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from haystack import Document
from haystack.document_stores.errors import MissingDocumentError
from haystack.document_stores.types import DuplicatePolicy
from haystack.testing.document_store import DocumentStoreBaseTests
from haystack.testing.document_store import DocumentStoreBaseExtendedTests

from haystack_integrations.document_stores.astra import AstraDocumentStore

Expand Down Expand Up @@ -48,9 +48,9 @@ def test_to_dict(mock_auth): # noqa
os.environ.get("ASTRA_DB_APPLICATION_TOKEN", "") == "", reason="ASTRA_DB_APPLICATION_TOKEN env var not set"
)
@pytest.mark.skipif(os.environ.get("ASTRA_DB_API_ENDPOINT", "") == "", reason="ASTRA_DB_API_ENDPOINT env var not set")
class TestDocumentStore(DocumentStoreBaseTests):
class TestDocumentStore(DocumentStoreBaseExtendedTests):
"""
Common test cases will be provided by `DocumentStoreBaseTests` but
Common test cases will be provided by `DocumentStoreBaseExtendedTests` but
you can add more to this class.
"""

Expand Down Expand Up @@ -204,74 +204,6 @@ def test_filter_documents_by_in_operator(self, document_store):
self.assert_documents_are_equal([result[0]], [docs[0]])
self.assert_documents_are_equal([result[1]], [docs[1]])

def test_delete_all_documents(self, document_store: AstraDocumentStore):
"""
Test delete_all_documents() on an Astra.
"""
document_store.delete_all_documents()
assert document_store.count_documents() == 0

def test_delete_by_filter(self, document_store: AstraDocumentStore, filterable_docs):
document_store.write_documents(filterable_docs)
initial_count = document_store.count_documents()
assert initial_count > 0

# count documents that match the filter before deletion
matching_docs = [d for d in filterable_docs if d.meta.get("chapter") == "intro"]
expected_deleted_count = len(matching_docs)

# delete all documents with chapter="intro"
deleted_count = document_store.delete_by_filter(
filters={"field": "meta.chapter", "operator": "==", "value": "intro"}
)

assert deleted_count == expected_deleted_count
assert document_store.count_documents() == initial_count - deleted_count

# remaining documents don't have chapter="intro"
remaining_docs = document_store.filter_documents()
for doc in remaining_docs:
assert doc.meta.get("chapter") != "intro"

# all documents with chapter="intro" were deleted
intro_docs = document_store.filter_documents(
filters={"field": "meta.chapter", "operator": "==", "value": "intro"}
)
assert len(intro_docs) == 0

def test_update_by_filter(self, document_store: AstraDocumentStore, filterable_docs):
document_store.write_documents(filterable_docs)
initial_count = document_store.count_documents()
assert initial_count > 0

# count documents that match the filter before update
matching_docs = [d for d in filterable_docs if d.meta.get("chapter") == "intro"]
expected_updated_count = len(matching_docs)

# update all documents with chapter="intro" to have status="updated"
updated_count = document_store.update_by_filter(
filters={"field": "meta.chapter", "operator": "==", "value": "intro"},
meta={"status": "updated"},
)

assert updated_count == expected_updated_count
assert document_store.count_documents() == initial_count

# verify the updated documents have the new metadata
updated_docs = document_store.filter_documents(
filters={"field": "meta.status", "operator": "==", "value": "updated"}
)
assert len(updated_docs) == expected_updated_count
for doc in updated_docs:
assert doc.meta.get("chapter") == "intro"
assert doc.meta.get("status") == "updated"

# verify other documents weren't affected
all_docs = document_store.filter_documents()
for doc in all_docs:
if doc.meta.get("chapter") != "intro":
assert doc.meta.get("status") != "updated"

@pytest.mark.skip(reason="Unsupported filter operator not.")
def test_not_operator(self, document_store, filterable_docs):
pass
Expand Down
6 changes: 5 additions & 1 deletion integrations/azure_ai_search/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ classifiers = [
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
]
dependencies = ["haystack-ai>=2.22.0", "azure-search-documents>=11.5", "azure-identity"]
dependencies = [
"haystack-ai>=2.24.0",
"azure-search-documents>=11.5",
"azure-identity"
]

[project.urls]
Documentation = "https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/azure_ai_search#readme"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,19 @@ def _parse_comparison_condition(condition: dict[str, Any]) -> str:


def _eq(field: str, value: Any) -> str:
return f"{field} eq '{value}'" if isinstance(value, str) and value != "null" else f"{field} eq {value}"
if isinstance(value, str) and value != "null":
return f"{field} eq '{value}'"
if isinstance(value, bool):
return f"{field} eq {str(value).lower()}"
return f"{field} eq {value}"


def _ne(field: str, value: Any) -> str:
return f"not ({field} eq '{value}')" if isinstance(value, str) and value != "null" else f"not ({field} eq {value})"
if isinstance(value, str) and value != "null":
return f"not ({field} eq '{value}')"
if isinstance(value, bool):
return f"not ({field} eq {str(value).lower()})"
return f"not ({field} eq {value})"


def _in(field: str, value: Any) -> str:
Expand Down
5 changes: 3 additions & 2 deletions integrations/azure_ai_search/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ def delete_by_filter_and_wait(filters):
time.sleep(SLEEP_TIME_IN_SECONDS)
return deleted_count

def update_by_filter_and_wait(filters, fields):
updated_count = original_update_by_filter(filters, fields)
def update_by_filter_and_wait(filters, meta=None, fields=None):
updates = meta if meta is not None else fields or {}
updated_count = original_update_by_filter(filters, updates)
time.sleep(SLEEP_TIME_IN_SECONDS)
return updated_count

Expand Down
150 changes: 61 additions & 89 deletions integrations/azure_ai_search/tests/test_document_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@
from haystack.errors import FilterError
from haystack.testing.document_store import (
CountDocumentsTest,
DeleteAllTest,
DeleteByFilterTest,
DeleteDocumentsTest,
FilterableDocsFixtureMixin,
FilterDocumentsTest,
UpdateByFilterTest,
WriteDocumentsTest,
)
from haystack.utils.auth import EnvVarSecret, Secret
Expand Down Expand Up @@ -256,7 +260,15 @@ def _assert_documents_are_equal(received: list[Document], expected: list[Documen
not os.environ.get("AZURE_AI_SEARCH_ENDPOINT", None) and not os.environ.get("AZURE_AI_SEARCH_API_KEY", None),
reason="Missing AZURE_AI_SEARCH_ENDPOINT or AZURE_AI_SEARCH_API_KEY.",
)
class TestDocumentStore(CountDocumentsTest, WriteDocumentsTest, DeleteDocumentsTest):
class TestDocumentStore(
CountDocumentsTest,
DeleteDocumentsTest,
DeleteAllTest,
DeleteByFilterTest,
FilterableDocsFixtureMixin,
WriteDocumentsTest,
UpdateByFilterTest,
):
def assert_documents_are_equal(self, received: list[Document], expected: list[Document]):
_assert_documents_are_equal(received, expected)

Expand Down Expand Up @@ -290,120 +302,80 @@ def test_write_documents_duplicate_fail(self, document_store: AzureAISearchDocum
@pytest.mark.skip(reason="Azure AI search index overwrites duplicate documents by default")
def test_write_documents_duplicate_skip(self, document_store: AzureAISearchDocumentStore): ...

def test_delete_all_documents(self, document_store: AzureAISearchDocumentStore):
docs = [Document(content="first doc"), Document(content="second doc")]
document_store.write_documents(docs)
assert document_store.count_documents() == 2
document_store.delete_all_documents()
assert document_store.count_documents() == 0

def test_delete_all_documents_empty_index(self, document_store: AzureAISearchDocumentStore):
assert document_store.count_documents() == 0
document_store.delete_all_documents()
assert document_store.count_documents() == 0

@pytest.mark.parametrize(
"document_store",
[{"metadata_fields": {"category": str}}],
indirect=True,
)
def test_delete_by_filter(self, document_store: AzureAISearchDocumentStore):
docs = [
Document(content="Doc 1", meta={"category": "A"}),
Document(content="Doc 2", meta={"category": "B"}),
Document(content="Doc 3", meta={"category": "A"}),
]
document_store.write_documents(docs)
assert document_store.count_documents() == 3

# Delete documents with category="A"
deleted_count = document_store.delete_by_filter(
filters={"field": "meta.category", "operator": "==", "value": "A"}
)
assert deleted_count == 2
assert document_store.count_documents() == 1

# Verify only category B remains
remaining_docs = document_store.filter_documents()
assert len(remaining_docs) == 1
assert remaining_docs[0].meta["category"] == "B"
"""Override to use a document_store with category metadata field."""
DeleteByFilterTest.test_delete_by_filter(document_store)

@pytest.mark.parametrize(
"document_store",
[{"metadata_fields": {"category": str}}],
indirect=True,
)
def test_delete_by_filter_no_matches(self, document_store: AzureAISearchDocumentStore):
docs = [
Document(content="Doc 1", meta={"category": "A"}),
Document(content="Doc 2", meta={"category": "B"}),
]
document_store.write_documents(docs)
assert document_store.count_documents() == 2

# Try to delete documents with category="C" (no matches)
deleted_count = document_store.delete_by_filter(
filters={"field": "meta.category", "operator": "==", "value": "C"}
)
assert deleted_count == 0
assert document_store.count_documents() == 2
"""Override to use a document_store with category metadata field."""
DeleteByFilterTest.test_delete_by_filter_no_matches(document_store)

@pytest.mark.parametrize(
"document_store",
[{"metadata_fields": {"category": str, "status": str}}],
[{"metadata_fields": {"category": str, "year": int, "status": str}}],
indirect=True,
)
def test_update_by_filter(self, document_store: AzureAISearchDocumentStore):
docs = [
Document(content="Doc 1", meta={"category": "A", "status": "draft"}),
Document(content="Doc 2", meta={"category": "B", "status": "draft"}),
Document(content="Doc 3", meta={"category": "A", "status": "draft"}),
]
document_store.write_documents(docs)
assert document_store.count_documents() == 3
def test_delete_by_filter_advanced_filters(self, document_store: AzureAISearchDocumentStore):
"""Override to use a document_store with category, year, status metadata fields."""
DeleteByFilterTest.test_delete_by_filter_advanced_filters(document_store)

# Metadata fields required by haystack UpdateByFilterTest filterable_docs (chapter, name, page, number, date, etc.)
_FILTERABLE_DOCS_METADATA = { # noqa: RUF012
"name": str,
"page": str,
"chapter": str,
"number": int,
"date": str,
"no_embedding": bool,
"updated": bool,
"extra_field": str,
}

# Update status for category="A" documents
updated_count = document_store.update_by_filter(
filters={"field": "meta.category", "operator": "==", "value": "A"},
fields={"status": "published"},
)
assert updated_count == 2
@pytest.mark.parametrize(
"document_store",
[{"metadata_fields": _FILTERABLE_DOCS_METADATA}],
indirect=True,
)
def test_update_by_filter(self, document_store: AzureAISearchDocumentStore, filterable_docs):
"""Override to use a document_store with metadata fields for filterable_docs."""
UpdateByFilterTest.test_update_by_filter(document_store, filterable_docs)

# Verify the updates
published_docs = document_store.filter_documents(
filters={"field": "meta.status", "operator": "==", "value": "published"}
)
assert len(published_docs) == 2
for doc in published_docs:
assert doc.meta["category"] == "A"
assert doc.meta["status"] == "published"

# Verify category B still has draft status
draft_docs = document_store.filter_documents(
filters={"field": "meta.status", "operator": "==", "value": "draft"}
)
assert len(draft_docs) == 1
assert draft_docs[0].meta["category"] == "B"
@pytest.mark.parametrize(
"document_store",
[{"metadata_fields": _FILTERABLE_DOCS_METADATA}],
indirect=True,
)
def test_update_by_filter_no_matches(self, document_store: AzureAISearchDocumentStore, filterable_docs):
"""Override to use a document_store with metadata fields for filterable_docs."""
UpdateByFilterTest.test_update_by_filter_no_matches(document_store, filterable_docs)

@pytest.mark.parametrize(
"document_store",
[{"metadata_fields": {"category": str, "status": str}}],
[{"metadata_fields": _FILTERABLE_DOCS_METADATA}],
indirect=True,
)
def test_update_by_filter_no_matches(self, document_store: AzureAISearchDocumentStore):
docs = [
Document(content="Doc 1", meta={"category": "A", "status": "draft"}),
Document(content="Doc 2", meta={"category": "B", "status": "draft"}),
]
document_store.write_documents(docs)
assert document_store.count_documents() == 2
def test_update_by_filter_multiple_fields(self, document_store: AzureAISearchDocumentStore, filterable_docs):
"""Override to use a document_store with metadata fields for filterable_docs."""
UpdateByFilterTest.test_update_by_filter_multiple_fields(document_store, filterable_docs)

# Try to update documents with category="C" (no matches)
updated_count = document_store.update_by_filter(
filters={"field": "meta.category", "operator": "==", "value": "C"},
fields={"status": "published"},
)
assert updated_count == 0
@pytest.mark.parametrize(
"document_store",
[{"metadata_fields": {"category": str, "year": int, "status": str, "featured": bool}}],
indirect=True,
)
def test_update_by_filter_advanced_filters(self, document_store: AzureAISearchDocumentStore):
"""Override to use a document_store with category, year, status, featured metadata fields."""
UpdateByFilterTest.test_update_by_filter_advanced_filters(document_store)

@pytest.mark.parametrize(
"document_store",
Expand Down
5 changes: 4 additions & 1 deletion integrations/chroma/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ classifiers = [
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
]
dependencies = ["haystack-ai>=2.22.0", "chromadb>=1.0.2"]
dependencies = [
"haystack-ai>=2.24.0",
"chromadb>=1.0.2"
]

[project.urls]
Documentation = "https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/chroma#readme"
Expand Down
Loading
Loading