Skip to content

Add MariaDB Vector DocumentStore integration - #3565

Open
SyedShahmeerAli12 wants to merge 28 commits into
deepset-ai:mainfrom
SyedShahmeerAli12:feat/mariadb-document-store-2340
Open

Add MariaDB Vector DocumentStore integration#3565
SyedShahmeerAli12 wants to merge 28 commits into
deepset-ai:mainfrom
SyedShahmeerAli12:feat/mariadb-document-store-2340

Conversation

@SyedShahmeerAli12

@SyedShahmeerAli12 SyedShahmeerAli12 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Part of #2340

Implements a complete MariaDB document store integration using MariaDB 11.7+ native VECTOR support.

  • MariaDBDocumentStore full DocumentStore protocol (write_documents, filter_documents, delete_documents, count_documents)
  • Vector similarity search using VEC_DISTANCE_COSINE / VEC_DISTANCE_EUCLIDEAN with MHNSW indexing
  • Full-text keyword search via MATCH ... AGAINST (IN NATURAL LANGUAGE MODE) on a FULLTEXT index
  • Haystack metadata filtering converted to JSON_UNQUOTE(JSON_EXTRACT(...)) SQL expressions with parameterized queries
  • MariaDBEmbeddingRetriever and MariaDBKeywordRetriever with FilterPolicy support
  • DuplicatePolicy support: FAIL (INSERT), OVERWRITE (upsert via ON DUPLICATE KEY UPDATE), SKIP (INSERT IGNORE)
  • Lazy connection with reconnect on ping failure

Tests

80 tests total all passing:

  • 68 unit tests (mocked DB, no external dependency)
  • 12 integration tests verified against a real MariaDB 11.7 Docker container

CI

Added .github/workflows/mariadb.yml with a MariaDB 11.7 service container, matching the pattern used by pgvector.

How to run locally

docker run -d --name mariadb-haystack \
  -e MARIADB_ROOT_PASSWORD=password \
  -e MARIADB_DATABASE=haystack \
  -p 3306:3306 mariadb:11.7

cd integrations/mariadb
pip install -e .
MARIADB_USER=root MARIADB_PASSWORD=password pytest tests/ -m integration

@SyedShahmeerAli12
SyedShahmeerAli12 requested a review from a team as a code owner July 8, 2026 13:59
@SyedShahmeerAli12
SyedShahmeerAli12 requested review from anakin87 and removed request for a team July 8, 2026 13:59
@github-actions github-actions Bot added topic:CI integration:tavily type:documentation Improvements or additions to documentation labels Jul 8, 2026
@socket-security

socket-security Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedpypi/​mariadb@​1.1.149810010010070

View full report

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Coverage report (tavily)

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  integrations/tavily/src/haystack_integrations/components/fetchers/tavily
  tavily_fetcher.py
Project Total  

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

Implements MariaDBDocumentStore backed by MariaDB 11.7+ native VECTOR
support with MHNSW indexing and full-text keyword search.

- Full DocumentStore protocol: write_documents (FAIL/OVERWRITE/SKIP),
  filter_documents, delete_documents, count_documents
- Vector similarity via VEC_DISTANCE_COSINE / VEC_DISTANCE_EUCLIDEAN
- Full-text keyword search via MATCH ... AGAINST (NATURAL LANGUAGE MODE)
- Haystack metadata filtering converted to JSON_EXTRACT SQL expressions
- MariaDBEmbeddingRetriever and MariaDBKeywordRetriever with FilterPolicy
- 80 tests: 68 unit + 12 integration (all verified against MariaDB 11.7)
- GitHub Actions workflow with MariaDB 11.7 service container

Closes deepset-ai#2340
- Make mariadb C extension import lazy so API reference builds without
  requiring libmariadb-dev in the docs environment
- Fix Docker health check to use --su-mysql flag required by MariaDB 11.7
- Add mariadb (LGPL-2.1) to license compliance exclusion list
@SyedShahmeerAli12
SyedShahmeerAli12 force-pushed the feat/mariadb-document-store-2340 branch from f71d1cd to ff12b6a Compare July 8, 2026 14:09
- Add skip-install=true to default hatch env so docs build does not
  attempt to compile the mariadb C extension (libmariadb-dev not
  available in the API reference runner). The pydoc search_path already
  points to src/ so modules are importable without installation.
- Switch service container health check from healthcheck.sh (unreliable
  in some MariaDB 11.7 images) to mysqladmin ping which is more robust.
…THCHECK

The mariadb:11.7 Docker image ships with a HEALTHCHECK instruction.
GitHub Actions automatically waits for it when no custom options override it.
Custom health-cmd variants (healthcheck.sh, mysqladmin) were failing because
the slim runner environment handles them differently.

@anakin87 anakin87 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took a first look and found some points to address and some others to discuss.

Comment thread integrations/mariadb/CHANGELOG.md Outdated
Comment thread integrations/mariadb/README.md Outdated
Comment thread integrations/mariadb/pyproject.toml
Comment thread integrations/mariadb/tests/test_document_store.py
@SyedShahmeerAli12

Copy link
Copy Markdown
Contributor Author

Addressed all the straightforward review comments. The HNSW index design (create_vector_index flag) and the lazy import approach are still open for discussion

@anakin87 anakin87 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are still some comments to address.

Please request my review when they are fixed. In the meantime, ask questions if needed.

@SyedShahmeerAli12
SyedShahmeerAli12 force-pushed the feat/mariadb-document-store-2340 branch from 93e2728 to 8f91d92 Compare July 23, 2026 10:10
@SyedShahmeerAli12

SyedShahmeerAli12 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

ruff auto-detects mariadb and haystack as separate import sections, so import mariadb must go in its own block after all from haystack imports.
Every attempt I made grouped them together, which ruff kept rejecting until I let --fix show me the exact layout it expected.

@SyedShahmeerAli12

Copy link
Copy Markdown
Contributor Author

I mistakently Referenced some PRs here , Well I have cleaned the mess the Code is opened for review

filters: dict[str, Any] | None = None,
top_k: int = 10,
score_threshold: float | None = None,
vector_function: str | None = None,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Searches using a different distance function will not be able to use a vector index

I'd simply not allow users to change the distance function at runtime, in other words by removing this parameter

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the misunderstanding. I meant:

  • let's make distance configurable in MariaDBDocumentStore.__init__ and take this parameter into account only when the table is created
  • do not expose distance in _embedding_retrieval

Comment thread integrations/mariadb/tests/test_document_store.py Outdated

@anakin87 anakin87 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are still a few rough edges to address in this PR, including some points that were left unresolved from the previous review.

Since this is a new integration, I'd like to see a more thorough pass: try it yourself, refine the implementation, and make sure to address the existing feedback.
Otherwise, I may need to deprioritize further review.

@SyedShahmeerAli12

Copy link
Copy Markdown
Contributor Author

Hi @anakin87 , I've addressed all of your review comments:

  • Removed DocumentStore protocol inheritance
  • Fixed the import order
  • Updated the vector index SQL to use VECTOR INDEX (embedding) (removed COMMENT 'MHNSW(...)')
  • Added HAVING score > 0 to the keyword search to filter out zero-score results
  • Changed user/password to use Secret only (removed the plain string fallback)
  • Removed the vector_function parameter from _embedding_retrieval (and the retriever)
  • Moved packaging>=21.3 to the main dependencies
  • Removed all section separator comments from the tests
  • Updated all test fixtures to use Secret.from_token()

I also verified everything against a real MariaDB 11.7 Docker instance all 120 tests are passing (65 unit + 55 integration).

Comment thread integrations/mariadb/pyproject.toml Outdated
Comment on lines +50 to +53
# skip-install prevents hatch from installing the project (and thus the mariadb C extension)
# in the docs environment. The pydoc search_path points to src/ so modules are found directly.
skip-install = true
dependencies = ["haystack-pydoc-tools", "ruff", "haystack-ai>=2.28.0"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# skip-install prevents hatch from installing the project (and thus the mariadb C extension)
# in the docs environment. The pydoc search_path points to src/ so modules are found directly.
skip-install = true
dependencies = ["haystack-pydoc-tools", "ruff", "haystack-ai>=2.28.0"]
dependencies = ["haystack-pydoc-tools", "ruff"]

filters: dict[str, Any] | None = None,
top_k: int = 10,
score_threshold: float | None = None,
vector_function: str | None = None,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the misunderstanding. I meant:

  • let's make distance configurable in MariaDBDocumentStore.__init__ and take this parameter into account only when the table is created
  • do not expose distance in _embedding_retrieval

value: Any = condition["value"]
sql_field = _build_field_expr(field, value)
clause, val = COMPARISON_OPERATORS[operator](sql_field, value)
# _in/_not_in return the value list directly; flatten it so params stay flat

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currently boolean meta filters seem to match nothing.
Try for example the condition {"field": "meta.flag", "operator": "==", "value": True}

:param score_threshold: Minimum score to include a document. Documents below this score are excluded.
:returns: List of Documents ordered by similarity (most similar first).
"""
_validate_filters(filters)

@anakin87 anakin87 Aug 10, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MariaDB does not raise an error if the query_embedding does not match the default embedding dimension but just returns records with null score. I propose raising an error ourselves.

@SyedShahmeerAli12

Copy link
Copy Markdown
Contributor Author

I did all the testing against MariaDB 11.7via Docker

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

Labels

integration:tavily topic:CI type:documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants