--- title: "Organizing & Filtering Memories" sidebarTitle: "Multi-Tenancy / Filtering" description: "Use container tags and metadata to organize and retrieve memories" icon: "users" --- Supermemory provides two ways to organize your memories: **Organize memories** into isolated spaces by user, project, or workspace **Query memories** by custom properties like category, status, or date Both can be used independently or together for precise filtering. --- ## Container Tags Container tags create isolated memory spaces. Use them to separate memories by user, project, or any logical boundary. ### Adding Memories with Tags ```typescript await client.add({ content: "Meeting notes from Q1 planning", containerTags: ["user_123"] }); ``` ### Searching with Tags ```typescript const results = await client.search.documents({ q: "planning notes", containerTags: ["user_123"] }); ``` Container tags use **exact array matching**. A memory tagged `["user_123", "project_a"]` won't match a search for just `["user_123"]`. ### Recommended Patterns | Pattern | Example | Use Case | |---------|---------|----------| | User isolation | `user_{userId}` | Per-user memories | | Project grouping | `project_{projectId}` | Project-specific content | | Hierarchical | `org_{orgId}_team_{teamId}` | Multi-level organization | ```typescript // Multi-tenant SaaS - isolate by organization and user await client.add({ content: "Company policy document", containerTags: ["org_acme_user_john"] }); // Search only within that user's org context const results = await client.search.documents({ q: "vacation policy", containerTags: ["org_acme_user_john"] }); // Project-based isolation await client.add({ content: "Sprint 5 retrospective notes", containerTags: ["project_mobile_app"] }); // Time-based segmentation await client.add({ content: "Q1 2024 financial report", containerTags: ["user_cfo_2024_q1"] }); ``` **API field differences:** | Endpoint | Field | Type | |----------|-------|------| | `/v3/search` | `containerTags` | Array | | `/v4/search` | `containerTag` | String | | `/v3/documents/list` | `containerTags` | Array | --- ## Metadata Metadata lets you attach custom properties to memories and filter by them later. ### Adding Memories with Metadata ```typescript await client.add({ content: "Technical design document for auth system", containerTags: ["user_123"], metadata: { category: "engineering", priority: "high", year: 2024 } }); ``` ### Searching with Metadata Filters Filters must be wrapped in `AND` or `OR` arrays: ```typescript const results = await client.search.documents({ q: "design document", containerTags: ["user_123"], filters: { AND: [ { key: "category", value: "engineering" }, { key: "priority", value: "high" } ] } }); ``` ### Filter Types | Type | Example | Description | |------|---------|-------------| | String equality | `{ key: "status", value: "published" }` | Exact match | | String contains | `{ filterType: "string_contains", key: "title", value: "react" }` | Substring match | | Numeric | `{ filterType: "numeric", key: "priority", value: "5", numericOperator: ">=" }` | Number comparison | | Array contains | `{ filterType: "array_contains", key: "tags", value: "important" }` | Check array membership | ### Combining Filters Use `AND` and `OR` for complex queries: ```typescript const results = await client.search.documents({ q: "meeting notes", filters: { AND: [ { key: "type", value: "meeting" }, { OR: [ { key: "team", value: "engineering" }, { key: "team", value: "product" } ] } ] } }); ``` ### Excluding Results Use `negate: true` to exclude matches: ```typescript const results = await client.search.documents({ q: "documentation", filters: { AND: [ { key: "status", value: "draft", negate: true } ] } }); ``` **String contains (substring search):** ```typescript // Find documents with "machine learning" in the description const results = await client.search.documents({ q: "AI research", filters: { AND: [ { filterType: "string_contains", key: "description", value: "machine learning", ignoreCase: true } ] } }); ``` **Numeric comparisons:** ```typescript // Find high-priority items created after a specific date const results = await client.search.documents({ q: "tasks", filters: { AND: [ { filterType: "numeric", key: "priority", value: "7", numericOperator: ">=" }, { filterType: "numeric", key: "created_timestamp", value: "1704067200", // Unix timestamp numericOperator: ">=" } ] } }); ``` **Array contains (check array membership):** ```typescript // Find documents where a specific user is a participant const results = await client.search.documents({ q: "meeting notes", filters: { AND: [ { filterType: "array_contains", key: "participants", value: "alice@company.com" } ] } }); ``` **Complex nested filters:** ```typescript // (category = "tech" OR category = "science") AND status != "archived" const results = await client.search.documents({ q: "research papers", filters: { AND: [ { OR: [ { key: "category", value: "tech" }, { key: "category", value: "science" } ] }, { key: "status", value: "archived", negate: true } ] } }); ``` **Numeric operator negation mapping:** When using `negate: true`, operators flip: - `<` becomes `>=` - `<=` becomes `>` - `>` becomes `<=` - `>=` becomes `<` - `=` becomes `!=` **User's work documents from 2024:** ```typescript const results = await client.search.documents({ q: "quarterly report", containerTags: ["user_123"], filters: { AND: [ { key: "category", value: "work" }, { key: "type", value: "report" }, { filterType: "numeric", key: "year", value: "2024", numericOperator: "=" } ] } }); ``` **Team meeting notes with specific participants:** ```typescript const results = await client.search.documents({ q: "sprint planning", containerTags: ["project_alpha"], filters: { AND: [ { key: "type", value: "meeting" }, { OR: [ { filterType: "array_contains", key: "participants", value: "alice" }, { filterType: "array_contains", key: "participants", value: "bob" } ] } ] } }); ``` **Exclude drafts and deprecated content:** ```typescript const results = await client.search.documents({ q: "documentation", filters: { AND: [ { key: "status", value: "draft", negate: true }, { filterType: "string_contains", key: "content", value: "deprecated", negate: true }, { filterType: "array_contains", key: "tags", value: "archived", negate: true } ] } }); ``` --- ## Quick Reference ### When Adding Memories ```typescript await client.add({ content: "Your content here", containerTags: ["user_123"], // Isolation metadata: { key: "value" } // Custom properties }); ``` ### When Searching ```typescript const results = await client.search.documents({ q: "search query", containerTags: ["user_123"], // Must match exactly filters: { // Optional metadata filters AND: [{ key: "status", value: "published" }] } }); ``` ### Metadata Key Rules - Allowed characters: `a-z`, `A-Z`, `0-9`, `_`, `-`, `.` - Max length: 64 characters - No spaces or special characters --- ## Next Steps Apply filters in search queries Add content with container tags and metadata