Skip to main content
Supermemory provides two complementary filtering mechanisms that work independently or together to help you find exactly what you need.

How Filtering Works

Supermemory uses two types of filters for different purposes:

Container Tags

Organize memories into isolated spaces by user, project, or workspace

Metadata Filtering

Query memories by custom properties like category, status, or date
Both filtering types can be used:
  • Independently - Use container tags alone OR metadata filters alone
  • Together - Combine both for precise filtering (most common)
Think of it as: [Container Tags] → [Your Memories] ← [Metadata Filters]

Container Tags

Container tags create isolated memory spaces. They’re perfect for multi-tenant applications, user profiles, and project organization.

How Container Tags Work

  • Exact matching: Arrays must match exactly. A memory tagged with ["user_123", "project_ai"] will NOT match a search for just ["user_123"]
  • Isolation: Each container tag combination creates a separate knowledge graph
  • Naming patterns: Use consistent patterns like user_{id}, project_{id}, or org_{id}_team_{id}

Basic Usage

  • TypeScript
  • Python
  • cURL
// Search within a user's memories
const results = await client.search.documents({
  q: "machine learning notes",
  containerTags: ["user_123"],
  limit: 10
});

// Search within a project
const projectResults = await client.search.documents({
  q: "requirements",
  containerTags: ["project_ai"],
  limit: 10
});

Container Tag Patterns

Best Practice: Use single container tags when possible. Multi-tag arrays require exact matching, which can be restrictive.
  • User isolation: user_{userId}
  • Project grouping: project_{projectId}
  • Workspace separation: workspace_{workspaceId}
  • Hierarchical: org_{orgId}_team_{teamId}
  • Temporal: user_{userId}_2024_q1

API Differences

EndpointField NameTypeExample
/v3/searchcontainerTagsArray["user_123"]
/v4/searchcontainerTagString"user_123"
/v3/documents/listcontainerTagsArray["user_123"]

Metadata Filtering

Metadata filters let you query memories by any custom property. They use SQL-like AND/OR logic with explicit grouping.

Filter Structure

All metadata filters must be wrapped in AND or OR arrays:
// ✅ Correct - wrapped in AND array
filters: {
  AND: [
    { key: "category", value: "tech", negate: false }
  ]
}

// ❌ Wrong - not wrapped
filters: {
  key: "category", value: "tech", negate: false
}

Why Explicit Grouping?

Without explicit grouping, this SQL query is ambiguous:
category = 'tech' OR status = 'published' AND priority = 'high'
Our structure forces clarity:
// Clear: (category = 'tech') OR (status = 'published' AND priority = 'high')
{
  OR: [
    { key: "category", value: "tech" },
    { AND: [
      { key: "status", value: "published" },
      { key: "priority", value: "high" }
    ]}
  ]
}

Basic Metadata Filtering

  • TypeScript
  • Python
  • cURL
// Single condition
const results = await client.search.documents({
  q: "neural networks",
  filters: {
    AND: [
      { key: "category", value: "ai", negate: false }
    ]
  },
  limit: 10
});

// Multiple AND conditions
const filtered = await client.search.documents({
  q: "research",
  filters: {
    AND: [
      { key: "category", value: "science", negate: false },
      { key: "status", value: "published", negate: false },
      { key: "year", value: "2024", negate: false }
    ]
  },
  limit: 10
});

Filter Types in Detail

Supermemory supports four filter types, each designed for specific use cases.

1. String Equality (Default)

Exact string matching with optional case-insensitive comparison.
  • Basic
  • Case-Insensitive
  • Negation
// Case-sensitive exact match (default)
{
  key: "status",
  value: "Published",
  negate: false
}

2. String Contains

Search for substrings within text fields.
  • Basic
  • Case-Insensitive
  • Exclusion
// Find all documents containing "machine learning"
{
  filterType: "string_contains",
  key: "description",
  value: "machine learning",
  negate: false
}

3. Numeric Comparisons

Filter by numeric values with comparison operators.
  • Basic Operators
  • With Negation
// Greater than or equal
{
  filterType: "numeric",
  key: "score",
  value: "80",
  numericOperator: ">=",
  negate: false
}

// Less than
{
  filterType: "numeric",
  key: "readingTime",
  value: "10",
  numericOperator: "<",
  negate: false
}
Numeric Negation Mapping: When using negate: true with numeric filters, operators are reversed:
  • <>=
  • <=>
  • ><=
  • >=<
  • =!=

4. Array Contains

Check if an array field contains a specific value.
  • Basic
  • Exclusion
  • Multiple Checks
// Find documents with specific participant
{
  filterType: "array_contains",
  key: "participants",
  value: "john.doe",
  negate: false
}

Common Patterns

Ready-to-use filtering patterns for common scenarios.

User-Specific Content with Category

  • TypeScript
  • Python
const results = await client.search.documents({
  q: "project updates",
  containerTags: ["user_123"],
  filters: {
    AND: [
      { key: "category", value: "work", negate: false },
      { key: "visibility", value: "private", negate: false }
    ]
  },
  limit: 10
});

Recent High-Priority Content

  • TypeScript
  • Python
const results = await client.search.documents({
  q: "important tasks",
  filters: {
    AND: [
      {
        filterType: "numeric",
        key: "priority",
        value: "7",
        numericOperator: ">=",
        negate: false
      },
      {
        filterType: "numeric",
        key: "created_timestamp",
        value: "1704067200", // 2024-01-01
        numericOperator: ">=",
        negate: false
      }
    ]
  },
  limit: 20
});

Team Collaboration Filter

  • TypeScript
  • Python
const results = await client.search.documents({
  q: "meeting notes",
  containerTags: ["project_alpha"],
  filters: {
    AND: [
      {
        OR: [
          {
            filterType: "array_contains",
            key: "participants",
            value: "alice"
          },
          {
            filterType: "array_contains",
            key: "participants",
            value: "bob"
          }
        ]
      },
      {
        key: "type",
        value: "meeting",
        negate: false
      }
    ]
  },
  limit: 15
});

Exclude Drafts and Deprecated Content

  • TypeScript
  • Python
const results = await client.search.documents({
  q: "documentation",
  filters: {
    AND: [
      {
        key: "status",
        value: "draft",
        negate: true  // Exclude drafts
      },
      {
        filterType: "string_contains",
        key: "content",
        value: "deprecated",
        negate: true  // Exclude deprecated
      },
      {
        filterType: "array_contains",
        key: "tags",
        value: "archived",
        negate: true  // Exclude archived
      }
    ]
  },
  limit: 10
});

API-Specific Notes

Different endpoints have slightly different requirements:
EndpointContainer Tag FieldTypeFilter FormatNotes
/v3/searchcontainerTagsArrayJSON objectDocument search
/v4/searchcontainerTagStringJSON objectMemory search
/v3/documents/listcontainerTagsArrayJSON stringMust use JSON.stringify()
List API Special Requirement: The /v3/documents/list endpoint requires filters as a JSON string:
// ✅ Correct for List API
filters: JSON.stringify({ AND: [...] })

// ❌ Wrong for List API (but correct for Search API)
filters: { AND: [...] }

Combining Container Tags and Metadata

Most real-world applications combine both filtering types for precise control.

Example: User’s Work Documents from 2024

  • TypeScript
  • Python
const results = await client.search.documents({
  q: "quarterly report",
  containerTags: ["user_123"],  // User isolation
  filters: {
    AND: [
      { key: "category", value: "work" },
      { key: "type", value: "report" },
      {
        filterType: "numeric",
        key: "year",
        value: "2024",
        numericOperator: "="
      }
    ]
  },
  limit: 10
});

Example: Project’s Active High-Priority Tasks

  • TypeScript
  • Python
const results = await client.search.documents({
  q: "implementation",
  containerTags: ["project_alpha"],  // Project isolation
  filters: {
    AND: [
      {
        key: "status",
        value: "completed",
        negate: true  // Not completed
      },
      {
        filterType: "numeric",
        key: "priority",
        value: "7",
        numericOperator: ">=",
        negate: false
      },
      {
        filterType: "array_contains",
        key: "assignees",
        value: "current_user"
      }
    ]
  },
  limit: 20
});
Search within a single large document using the docId parameter:
  • TypeScript
  • Python
// Search within a specific book or manual
const results = await client.search.documents({
  q: "neural architecture",
  docId: "doc_textbook_ml_2024",
  limit: 20
});
Use this for:
  • Large textbooks or manuals
  • Multi-chapter books
  • Long podcast transcripts
  • Course materials

Validation & Limits

Metadata Key Requirements

  • Pattern: /^[a-zA-Z0-9_.-]+$/
  • Allowed: Letters, numbers, underscore, hyphen, dot
  • Max length: 64 characters
  • No spaces or special characters

Valid vs Invalid Keys

// ✅ Valid keys
"user_email"
"created-date"
"version.number"
"priority_level_2"

// ❌ Invalid keys
"user email"        // Spaces not allowed
"created@date"      // @ not allowed
"priority!"         // ! not allowed
"very_long_key_name_that_exceeds_64_characters_limit"  // Too long

Query Complexity Limits

  • Maximum conditions: 200 per query
  • Maximum nesting depth: 8 levels
  • Container tag arrays: Must match exactly

Troubleshooting

No Results Returned

Problem: Container tags must match exactly as arrays.Solution: Verify the exact array structure. ["user_123"]["user_123", "project_1"]
Problem: Keys are case-sensitive by default.Solution: Check exact key spelling and casing, or use ignoreCase: true for values.
Problem: Using negate: true when you meant false.Solution: Review your negate values. false = include, true = exclude.

Validation Errors

Error: “Invalid metadata key: contains unsafe characters”Solution: Remove spaces, special characters. Use only alphanumeric, underscore, hyphen, dot.
Error: “Invalid filter structure”Solution: Ensure all conditions are wrapped in AND or OR arrays.
Error: “Invalid filter format”Solution: For /v3/documents/list, use JSON.stringify() on the filter object.

Performance Issues

Problem: Complex nested OR conditions with many branches.Solution: Simplify logic, reduce nesting, or split into multiple queries.
Problem: “Query exceeds maximum complexity”Solution: Reduce conditions (max 200) or nesting depth (max 8).