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
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,7 @@ def get_metadata_field_unique_values(
search_term: str | None = None,
from_: int = 0,
size: int = 10,
filters: dict[str, Any] | None = None,
) -> tuple[list[Any], int]:
"""
Get unique values for a given metadata field, optionally filtered by a search term.
Expand All @@ -619,6 +620,7 @@ def get_metadata_field_unique_values(
are considered.
:param from_: The offset for pagination (0-based).
:param size: The number of unique values to return.
:param filters: Optional filters to restrict the documents considered.
:return: A tuple containing (list of unique values in their original JSON type, total count of
unique values matching `search_term`).
"""
Expand All @@ -628,12 +630,19 @@ def get_metadata_field_unique_values(
# applied directly to a JSON_VALUE(...) expression derived from the BLOB `meta` column. Wrapping
# the extraction in a derived table materializes it as a plain VARCHAR column first, so DISTINCT
# and ORDER BY in the outer query operate on that column instead of the LOB-derived expression.
# `filters` is applied inside this subquery (not the outer one) since it references the raw
# `meta` column, which only exists at this level — the outer query only sees the extracted `value`.
params: list[Any] = []
filter_where = ""
if filters:
filter_expression = FilterTranslator().translate(filters, params)
filter_where = f" WHERE {filter_expression}"

value_subquery = (
f"SELECT JSON_VALUE(SYSTOOLS.BSON2JSON(meta), '$.{field_name}' RETURNING VARCHAR(1000)) AS value "
f"FROM {self.table_name}"
f"FROM {self.table_name}{filter_where}"
)

params: list[Any] = []
search_clause = ""
if search_term is not None:
search_clause = " AND LOCATE(UPPER(?), UPPER(value)) > 0"
Expand Down
13 changes: 13 additions & 0 deletions integrations/ibm_db/tests/test_document_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,19 @@ def test_get_metadata_field_unique_values_preserves_non_string_types(self, docum
assert set(values) == {1, 2}
assert total == 2

def test_get_metadata_field_unique_values_with_filters(self, document_store: IBMDb2DocumentStore):
docs = [
Document(content="Doc 1", meta={"category": "A", "status": "active"}),
Document(content="Doc 2", meta={"category": "B", "status": "active"}),
Document(content="Doc 3", meta={"category": "C", "status": "inactive"}),
]
document_store.write_documents(docs)

filters = {"field": "meta.status", "operator": "==", "value": "active"}
values, total = document_store.get_metadata_field_unique_values("category", filters=filters)
assert set(values) == {"A", "B"}
assert total == 2

def test_get_metadata_field_unique_values_invalid_field_name(self, document_store: IBMDb2DocumentStore):
with pytest.raises(ValueError, match="Invalid metadata field name"):
document_store.get_metadata_field_unique_values("field' OR '1'='1")
Expand Down
Loading