Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
46 changes: 26 additions & 20 deletions haystack/testing/document_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -1028,16 +1028,16 @@ def test_count_unique_metadata_by_filter_all_documents(document_store: DocumentS
counts = document_store.count_unique_metadata_by_filter( # type:ignore[attr-defined]
filters={}, metadata_fields=["category", "status", "priority"]
)
assert counts["category"] == 3
assert counts["status"] == 2
assert counts["priority"] == 3
assert counts == {"category": 3, "status": 2, "priority": 3}

@staticmethod
def test_count_unique_metadata_by_filter_with_filter(document_store: DocumentStore):
"""Test count_unique_metadata_by_filter() with a filter."""
# The filtered-out document carries extra unique values, so the counts only come out right
# when the store actually applies the filter.
docs = [
Document(content="Doc 1", meta={"category": "A", "status": "active", "priority": 1}),
Document(content="Doc 2", meta={"category": "B", "status": "active", "priority": 2}),
Document(content="Doc 2", meta={"category": "B", "status": "archived", "priority": 2}),
Document(content="Doc 3", meta={"category": "A", "status": "inactive", "priority": 1}),
Document(content="Doc 4", meta={"category": "A", "status": "active", "priority": 3}),
]
Expand All @@ -1047,8 +1047,7 @@ def test_count_unique_metadata_by_filter_with_filter(document_store: DocumentSto
counts = document_store.count_unique_metadata_by_filter( # type:ignore[attr-defined]
filters={"field": "meta.category", "operator": "==", "value": "A"}, metadata_fields=["status", "priority"]
)
assert counts["status"] == 2
assert counts["priority"] == 2
assert counts == {"status": 2, "priority": 2}

@staticmethod
def test_count_unique_metadata_by_filter_with_multiple_filters(document_store: DocumentStore):
Expand Down Expand Up @@ -1121,11 +1120,14 @@ class GetMetadataFieldMinMaxTest:
@staticmethod
def test_get_metadata_field_min_max_numeric(document_store: DocumentStore):
"""Test get_metadata_field_min_max() with integer field."""
# The min and max are deliberately not the first or last written values, so an implementation
# returning values by insertion order fails. Keeping both 10 and 5 catches implementations that
# compare numbers as strings ("10" < "5" lexicographically).
docs = [
Document(content="Doc 1", meta={"priority": 1}),
Document(content="Doc 2", meta={"priority": 5}),
Document(content="Doc 3", meta={"priority": 3}),
Document(content="Doc 4", meta={"priority": 10}),
Document(content="Doc 1", meta={"priority": 5}),
Document(content="Doc 2", meta={"priority": 1}),
Document(content="Doc 3", meta={"priority": 10}),
Document(content="Doc 4", meta={"priority": 3}),
]
document_store.write_documents(docs)
assert document_store.count_documents() == 4
Expand All @@ -1137,13 +1139,15 @@ def test_get_metadata_field_min_max_numeric(document_store: DocumentStore):
@staticmethod
def test_get_metadata_field_min_max_float(document_store: DocumentStore):
"""Test get_metadata_field_min_max() with float field."""
# The min and max are deliberately not the first or last written values.
docs = [
Document(content="Doc 1", meta={"rating": 0.6}),
Document(content="Doc 2", meta={"rating": 0.95}),
Document(content="Doc 3", meta={"rating": 0.8}),
Document(content="Doc 1", meta={"rating": 0.8}),
Document(content="Doc 2", meta={"rating": 0.6}),
Document(content="Doc 3", meta={"rating": 0.95}),
Document(content="Doc 4", meta={"rating": 0.7}),
]
document_store.write_documents(docs)
assert document_store.count_documents() == 3
assert document_store.count_documents() == 4

result = document_store.get_metadata_field_min_max("rating") # type:ignore[attr-defined]

Expand Down Expand Up @@ -1173,15 +1177,16 @@ def test_get_metadata_field_min_max_empty_collection(document_store: DocumentSto
@staticmethod
def test_get_metadata_field_min_max_meta_prefix(document_store: DocumentStore):
"""Test get_metadata_field_min_max() with field names that include 'meta.' prefix."""
# The min and max of each field are deliberately not the first or last written values.
docs = [
Document(content="Doc 1", meta={"priority": 1, "age": 10}),
Document(content="Doc 2", meta={"priority": 5, "age": 20}),
Document(content="Doc 3", meta={"priority": 3, "age": 15}),
Document(content="Doc 4", meta={"priority": 10, "age": 5}),
Document(content="Doc 1", meta={"priority": 5, "age": 10}),
Document(content="Doc 2", meta={"priority": 1, "age": 20}),
Document(content="Doc 3", meta={"priority": 10, "age": 15}),
Document(content="Doc 4", meta={"priority": 3, "age": 5}),
Document(content="Doc 6", meta={"rating": 10.5}),
Document(content="Doc 7", meta={"rating": 20.3}),
Document(content="Doc 8", meta={"rating": 15.7}),
Document(content="Doc 9", meta={"rating": 5.2}),
Document(content="Doc 8", meta={"rating": 5.2}),
Document(content="Doc 9", meta={"rating": 15.7}),
]
document_store.write_documents(docs)

Expand Down Expand Up @@ -1233,6 +1238,7 @@ def test_get_metadata_field_unique_values_basic(document_store: DocumentStore):

values = result[0] if isinstance(result, tuple) else result
assert isinstance(values, list)
assert len(values) == 3 # the returned values must not contain duplicates
assert set(values) == {"A", "B", "C"}
if isinstance(result, tuple) and len(result) >= 2 and isinstance(result[1], int):
assert result[1] == 3
Expand Down
46 changes: 26 additions & 20 deletions haystack/testing/document_store_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,17 +277,17 @@ async def test_count_unique_metadata_by_filter_async_all_documents(document_stor
counts = await document_store.count_unique_metadata_by_filter_async( # type:ignore[attr-defined]
filters={}, metadata_fields=["category", "status", "priority"]
)
assert counts["category"] == 3
assert counts["status"] == 2
assert counts["priority"] == 3
assert counts == {"category": 3, "status": 2, "priority": 3}

@staticmethod
@pytest.mark.asyncio
async def test_count_unique_metadata_by_filter_async_with_filter(document_store: AsyncDocumentStore):
"""Test count_unique_metadata_by_filter_async() with a filter."""
# The filtered-out document carries extra unique values, so the counts only come out right
# when the store actually applies the filter.
docs = [
Document(content="Doc 1", meta={"category": "A", "status": "active", "priority": 1}),
Document(content="Doc 2", meta={"category": "B", "status": "active", "priority": 2}),
Document(content="Doc 2", meta={"category": "B", "status": "archived", "priority": 2}),
Document(content="Doc 3", meta={"category": "A", "status": "inactive", "priority": 1}),
Document(content="Doc 4", meta={"category": "A", "status": "active", "priority": 3}),
]
Expand All @@ -297,8 +297,7 @@ async def test_count_unique_metadata_by_filter_async_with_filter(document_store:
counts = await document_store.count_unique_metadata_by_filter_async( # type:ignore[attr-defined]
filters={"field": "meta.category", "operator": "==", "value": "A"}, metadata_fields=["status", "priority"]
)
assert counts["status"] == 2
assert counts["priority"] == 2
assert counts == {"status": 2, "priority": 2}

@staticmethod
@pytest.mark.asyncio
Expand Down Expand Up @@ -622,11 +621,14 @@ class GetMetadataFieldMinMaxAsyncTest:
@pytest.mark.asyncio
async def test_get_metadata_field_min_max_numeric_async(document_store: AsyncDocumentStore):
"""Test get_metadata_field_min_max_async() with integer field."""
# The min and max are deliberately not the first or last written values, so an implementation
# returning values by insertion order fails. Keeping both 10 and 5 catches implementations that
# compare numbers as strings ("10" < "5" lexicographically).
docs = [
Document(content="Doc 1", meta={"priority": 1}),
Document(content="Doc 2", meta={"priority": 5}),
Document(content="Doc 3", meta={"priority": 3}),
Document(content="Doc 4", meta={"priority": 10}),
Document(content="Doc 1", meta={"priority": 5}),
Document(content="Doc 2", meta={"priority": 1}),
Document(content="Doc 3", meta={"priority": 10}),
Document(content="Doc 4", meta={"priority": 3}),
]
await document_store.write_documents_async(docs)
assert await document_store.count_documents_async() == 4
Expand All @@ -639,13 +641,15 @@ async def test_get_metadata_field_min_max_numeric_async(document_store: AsyncDoc
@pytest.mark.asyncio
async def test_get_metadata_field_min_max_float_async(document_store: AsyncDocumentStore):
"""Test get_metadata_field_min_max_async() with float field."""
# The min and max are deliberately not the first or last written values.
docs = [
Document(content="Doc 1", meta={"rating": 0.6}),
Document(content="Doc 2", meta={"rating": 0.95}),
Document(content="Doc 3", meta={"rating": 0.8}),
Document(content="Doc 1", meta={"rating": 0.8}),
Document(content="Doc 2", meta={"rating": 0.6}),
Document(content="Doc 3", meta={"rating": 0.95}),
Document(content="Doc 4", meta={"rating": 0.7}),
]
await document_store.write_documents_async(docs)
assert await document_store.count_documents_async() == 3
assert await document_store.count_documents_async() == 4

result = await document_store.get_metadata_field_min_max_async("rating") # type:ignore[attr-defined]

Expand Down Expand Up @@ -678,15 +682,16 @@ async def test_get_metadata_field_min_max_empty_collection_async(document_store:
@pytest.mark.asyncio
async def test_get_metadata_field_min_max_meta_prefix_async(document_store: AsyncDocumentStore):
"""Test get_metadata_field_min_max_async() with field names that include 'meta.' prefix."""
# The min and max of each field are deliberately not the first or last written values.
docs = [
Document(content="Doc 1", meta={"priority": 1, "age": 10}),
Document(content="Doc 2", meta={"priority": 5, "age": 20}),
Document(content="Doc 3", meta={"priority": 3, "age": 15}),
Document(content="Doc 4", meta={"priority": 10, "age": 5}),
Document(content="Doc 1", meta={"priority": 5, "age": 10}),
Document(content="Doc 2", meta={"priority": 1, "age": 20}),
Document(content="Doc 3", meta={"priority": 10, "age": 15}),
Document(content="Doc 4", meta={"priority": 3, "age": 5}),
Document(content="Doc 6", meta={"rating": 10.5}),
Document(content="Doc 7", meta={"rating": 20.3}),
Document(content="Doc 8", meta={"rating": 15.7}),
Document(content="Doc 9", meta={"rating": 5.2}),
Document(content="Doc 8", meta={"rating": 5.2}),
Document(content="Doc 9", meta={"rating": 15.7}),
]
await document_store.write_documents_async(docs)

Expand Down Expand Up @@ -739,6 +744,7 @@ async def test_get_metadata_field_unique_values_basic_async(document_store: Asyn

values = result[0] if isinstance(result, tuple) else result
assert isinstance(values, list)
assert len(values) == 3 # the returned values must not contain duplicates
assert set(values) == {"A", "B", "C"}
if isinstance(result, tuple) and len(result) >= 2 and isinstance(result[1], int):
assert result[1] == 3
Expand Down
Loading