fix(qdrant): implement enhanced metadata filtering operators#4127
Merged
whysosaket merged 10 commits intomem0ai:mainfrom Mar 21, 2026
Merged
fix(qdrant): implement enhanced metadata filtering operators#4127whysosaket merged 10 commits intomem0ai:mainfrom
whysosaket merged 10 commits intomem0ai:mainfrom
Conversation
The Qdrant vector store's _create_filter only handled simple equality and a single gte+lte range case, causing ValidationError for all other operators documented at docs.mem0.ai/open-source/features/metadata-filtering. Add _build_field_condition to translate the universal filter syntax into Qdrant-native models: - Comparison: eq, ne, gt, gte, lt, lte → MatchValue / MatchExcept / Range - List: in, nin → MatchAny / MatchExcept - String: contains, icontains → MatchText - Logical: AND, OR, NOT → Filter(must/should/must_not), recursive Existing simple equality and gte+lte range filters continue to work unchanged (backward compatible). Closes mem0ai#3975
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Raise ValueError when a filter dict for a single field combines range operators (gt/gte/lt/lte) with non-range operators (eq/ne/in/nin/etc), preventing silent data loss where the non-range conditions were dropped. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wildcard '*' values now return None from _build_field_condition (match any / field exists semantics), and _create_filter skips None conditions so a filter containing only wildcards returns None. Updated return type annotations to Optional[FieldCondition] and Optional[Filter] accordingly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Corrects the MatchText comment to accurately describe Qdrant behavior (tokenized match with a full-text index; exact substring without one), and adds ValueError validation when AND/OR/NOT filter values are not lists, replacing unhelpful AttributeError crashes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Memory._process_metadata_filters() renames OR→$or and NOT→$not before passing filters to the vector store. Without this fix, $or/$not keys with list values hit _build_field_condition and crash with ValidationError (MatchValue rejects lists). Normalize $or→OR, $not→NOT, $and→AND at the start of _create_filter so both naming conventions work. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Memory._process_metadata_filters() renames OR→$or and NOT→$not, but
effective_filters also retains the original OR/NOT keys from the
deepcopy of input_filters. Without dedup, the same sub-conditions were
evaluated twice in the Qdrant filter.
Normalize the filter dict upfront so $or/$not/$and map to OR/NOT/AND
and only the first occurrence is kept. Also replace the fragile
value.get("contains") or value.get("icontains") pattern with explicit
key lookup, and add a logger.debug for icontains explaining that Qdrant
MatchText case sensitivity depends on full-text index configuration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ator items
List values passed directly (e.g. {"tags": ["a", "b"]}) now map to
MatchAny instead of crashing with a Pydantic ValidationError. Non-dict
items inside AND/OR/NOT lists now raise a clear ValueError with the
index and value, instead of an AttributeError on .items().
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
whysosaket
approved these changes
Mar 21, 2026
This was referenced Mar 21, 2026
lukaj99
added a commit
to lukaj99/mem0
that referenced
this pull request
Mar 21, 2026
4 tasks
jamebobob
pushed a commit
to jamebobob/mem0-vigil-recall
that referenced
this pull request
Mar 29, 2026
…4127) Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3975
The Qdrant vector store's _create_filter only handled simple equality and a single gte+lte range case, causing ValidationError for all other operators documented at docs.mem0.ai/open-source/features/metadata-filtering.
Add _build_field_condition to translate the universal filter syntax into Qdrant-native models:
Existing simple equality and gte+lte range filters continue to work unchanged (backward compatible).