Skip to content

fix(chroma): split AND filters that mix content and metadata conditions - #4187

Open
mmporong wants to merge 1 commit into
deepset-ai:mainfrom
mmporong:fix-chroma-mixed-and-filter
Open

mmporong wants to merge 1 commit into
deepset-ai:mainfrom
mmporong:fix-chroma-mixed-and-filter

Conversation

@mmporong

@mmporong mmporong commented Nov 3, 2026

Copy link
Copy Markdown

Related Issues

  • No existing issue that I could find.

Proposed Changes:

_create_where_document_filter decides whether a logical filter is a content filter by looking only at its first condition (value[0]). For an AND that mixes a content condition and a metadata condition, the result depends on the order:

  • metadata condition first: the whole $and goes to Chroma's where, so content is treated as a metadata key and the filter silently matches nothing;
  • content condition first: every condition is converted as a document filter, and the metadata one makes the filter fail with ChromaDocumentStoreFilterError: Invalid 'document content filter' : Expected where document to have exactly one operator.

In Haystack's filter syntax the order of AND conditions does not matter. Chroma applies where and where_document together, so _convert_filters now sends the content conditions of a top-level AND to where_document and the other conditions to where, in either order. If the non-content part itself contains a content condition (for example nested under OR), the previous code path is used unchanged.

How did you test it?

  • New unit tests in tests/test_filters.py: the mixed AND in both orders, and one content condition with two metadata conditions. All three fail before the change and pass after it.
  • pytest tests -m "not integration" in integrations/chroma: 56 passed (53 passed and 3 failed before).
  • With a real in-memory ChromaDocumentStore and three documents, filter_documents with content contains "x" AND meta.a == 1 returned [] (metadata first) or raised (content first) before the change, and returns the matching document in both orders after it. I did not run the integration-marked tests.
  • ruff check and ruff format --check pass on the changed files.

Notes for the reviewer

Open PRs #4124 (metadata id filters) and #3797 (empty filter conditions) touch the same module but different cases. An OR that mixes content and metadata conditions cannot be expressed with Chroma's two separate clauses and is not changed here.

Checklist

_create_where_document_filter only looked at the first condition of a
logical operator. An AND with a metadata condition first was sent to
Chroma's where clause as a whole, so the content condition became a
metadata key and the filter silently matched nothing; with the content
condition first, the same filter raised ChromaDocumentStoreFilterError.
Chroma applies where and where_document together, so send the content
and metadata conditions of a top-level AND to the two clauses.
@mmporong
mmporong requested a review from a team as a code owner November 3, 2026 02:14
@mmporong
mmporong requested review from bogdankostic and removed request for a team November 3, 2026 02:14
@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Coverage report (chroma)

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  integrations/chroma/src/haystack_integrations/document_stores/chroma
  filters.py
Project Total  

This report was generated by python-coverage-comment-action

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant