Skip to main content
Enhanced metadata filtering in Mem0 lets you run complex queries across memory metadata. Combine comparisons, logical operators, and wildcard matches to zero in on the exact memories your agent needs.
This page covers the self-hosted Memory / AsyncMemory grammar. Sibling top-level keys are implicitly ANDed on both self-hosted and the hosted Platform API, so a flat filter like {"user_id": "alice", "category": "work"} works without wrapping it in AND on either. Two real differences remain: the nin operator documented below is not part of the Platform contract, and Platform validates every top-level key against a fixed allow-list, rejecting anything else with a 400. See Memory Filters (Platform) for the hosted grammar.

Feature anatomy

Metadata selectors

Start with key-value filters when you need direct matches on metadata fields.
Expect only memories tagged with category="preferences" to return for the given user_id.

Comparison operators

Layer greater-than/less-than comparisons to rank results by score, confidence, or any numeric field. Equality helpers (eq, ne) keep string and boolean checks explicit.

List-based operators

Use in and nin when you want to pre-approve or exclude specific values without writing multiple equality checks.
Verify the response includes only memories in the whitelisted categories and omits any with archived or deleted status.

String operators

contains and icontains capture substring matches, making it easy to scan descriptions or tags for keywords without retrieving irrelevant memories.

Wildcard matching

Match any value for a field, handy when the mere presence of a field matters.
Wildcard semantics differ by vector store. pgvector requires the key to exist in the payload (a real “field exists” check). Qdrant and Chroma have no native “field exists” filter, so * is a no-op there: the field condition is dropped and every record passes, including ones where the field is missing entirely. Do not rely on * to exclude records with a missing field unless you have confirmed your store’s behavior in mem0/vector_stores/<provider>.py.

Logical combinations

Combine filters with AND, OR, and NOT to express complex decision trees. Nest logical operators to encode multi-branch workflows.
The examples on this page use search(). get_all() accepts the same entity and comparison-operator filters, but the AND / OR / NOT wrapper is only translated at the search() layer before it reaches the vector store. Whether it also works on get_all() depends on your vector store: Qdrant recognizes raw AND / OR / NOT keys natively, but pgvector does not, so a logical wrapper passed to get_all() on pgvector silently matches nothing. Stick to search() for logical trees, or use plain sibling keys (implicitly ANDed) with get_all().
Inspect the response metadata: each returned memory should satisfy the combined logic tree exactly. If results look too broad, log the raw filters sent to your vector store.

Configure it

Tune your vector store so filter-heavy queries stay fast. Index fields you frequently filter on and keep complex checks for later in the evaluation order.
After enabling indexing, benchmark the same query: latency should drop once the store can prune documents on indexed fields before vector scoring.
Put simple key=value filters on indexed fields before your range or text conditions so the store trims results early.
When you reorder filters so indexed fields come first (good_filters example), queries typically return faster than the avoid_filters pattern where expensive text searches run before simple checks.
Vector store support varies widely. This table reflects what each provider’s filter-translation code (mem0/vector_stores/<provider>.py) actually implements, confirm before shipping if you use a store not listed:
If an operator is unsupported, most stores silently ignore it or fall back to equality rather than raising an error. Test filters against your actual store instead of assuming operator parity with Qdrant.

Migrate from earlier filters

Existing equality filters continue to work; add new operator branches gradually so agents can adopt richer queries without downtime.

See it in action

Project management filtering

Tasks returned should belong to the targeted projects, remain incomplete, and be assigned to one of the listed teammates.

Customer support filtering

Pair agent ID filters with ticket-specific metadata so shared support bots return only the tickets they can act on in the current session.

Content recommendation filtering

Confirm personalized feeds show only unread titles that meet the rating and language criteria.

Handle invalid operators

Validate filters before executing searches so you can catch typos or unsupported operators during development instead of at runtime.

Verify the feature is working

  • Log the filters sent to your vector store and confirm the response metadata matches every clause.
  • Benchmark queries before and after indexing to ensure latency improvements materialize.
  • Add analytics or debug logging to track how often fallbacks execute when operators fail validation.

Best practices

  1. Use indexed fields first: Order filters so equality checks run before complex string operations.
  2. Combine operators intentionally: Keep logical trees readable: large nests are harder to debug.
  3. Test performance regularly: Benchmark critical queries with production-like payloads.
  4. Plan graceful degradation: Provide fallback filters when an operator isn’t available.
  5. Validate syntax early: Catch malformed filters during development to protect agents at runtime.

Explore Vector Store Options

Compare operator coverage and indexing strategies across supported stores.

Tag and Organize Memories

Practice building workflows that label and retrieve memories with clear metadata filters.

Memory Filters (Platform)

Using the hosted API instead? See the allow-listed top-level fields, the missing nin operator, and Platform-only fields like created_at and memory_ids.