zilmate 1.8.0 → 1.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/copywriting/SKILL.md +252 -0
- package/.agents/skills/copywriting/evals/evals.json +111 -0
- package/.agents/skills/copywriting/references/copy-frameworks.md +344 -0
- package/.agents/skills/copywriting/references/natural-transitions.md +272 -0
- package/.agents/skills/firecrawl-deep-research/SKILL.md +108 -0
- package/.agents/skills/shadcn/SKILL.md +267 -0
- package/.agents/skills/shadcn/agents/openai.yml +5 -0
- package/.agents/skills/shadcn/assets/shadcn-small.png +0 -0
- package/.agents/skills/shadcn/assets/shadcn.png +0 -0
- package/.agents/skills/shadcn/cli.md +290 -0
- package/.agents/skills/shadcn/customization.md +209 -0
- package/.agents/skills/shadcn/evals/evals.json +47 -0
- package/.agents/skills/shadcn/mcp.md +105 -0
- package/.agents/skills/shadcn/registry.md +277 -0
- package/.agents/skills/shadcn/rules/base-vs-radix.md +306 -0
- package/.agents/skills/shadcn/rules/composition.md +195 -0
- package/.agents/skills/shadcn/rules/forms.md +192 -0
- package/.agents/skills/shadcn/rules/icons.md +101 -0
- package/.agents/skills/shadcn/rules/styling.md +162 -0
- package/.agents/skills/tavily-research/SKILL.md +100 -0
- package/.agents/skills/upstash/SKILL.md +48 -0
- package/.agents/skills/upstash/upstash-box-js/overview.md +243 -0
- package/.agents/skills/upstash/upstash-box-py/overview.md +275 -0
- package/.agents/skills/upstash/upstash-cli/overview.md +138 -0
- package/.agents/skills/upstash/upstash-qstash-js/advanced/callbacks.md +147 -0
- package/.agents/skills/upstash/upstash-qstash-js/advanced/deduplication.md +86 -0
- package/.agents/skills/upstash/upstash-qstash-js/advanced/dlq.md +164 -0
- package/.agents/skills/upstash/upstash-qstash-js/advanced/multi-region/summary.md +388 -0
- package/.agents/skills/upstash/upstash-qstash-js/advanced/multi-region/verify-multi-region-setup.ts +388 -0
- package/.agents/skills/upstash/upstash-qstash-js/fundamentals/local-development.md +106 -0
- package/.agents/skills/upstash/upstash-qstash-js/fundamentals/publishing-messages.md +144 -0
- package/.agents/skills/upstash/upstash-qstash-js/fundamentals/queues-and-flow-control.md +148 -0
- package/.agents/skills/upstash/upstash-qstash-js/fundamentals/schedules.md +177 -0
- package/.agents/skills/upstash/upstash-qstash-js/fundamentals/url-groups.md +127 -0
- package/.agents/skills/upstash/upstash-qstash-js/overview.md +81 -0
- package/.agents/skills/upstash/upstash-qstash-js/verification/platform-specific/nextjs.md +171 -0
- package/.agents/skills/upstash/upstash-qstash-js/verification/receiver.md +213 -0
- package/.agents/skills/upstash/upstash-ratelimit-js/algorithms.md +84 -0
- package/.agents/skills/upstash/upstash-ratelimit-js/features.md +117 -0
- package/.agents/skills/upstash/upstash-ratelimit-js/methods-getting-started.md +77 -0
- package/.agents/skills/upstash/upstash-ratelimit-js/overview.md +26 -0
- package/.agents/skills/upstash/upstash-ratelimit-js/pricing-cost.md +146 -0
- package/.agents/skills/upstash/upstash-ratelimit-js/traffic-protection.md +77 -0
- package/.agents/skills/upstash/upstash-redis-js/advanced-features/auto-pipeline.md +49 -0
- package/.agents/skills/upstash/upstash-redis-js/advanced-features/pipeline-and-transactions.md +42 -0
- package/.agents/skills/upstash/upstash-redis-js/advanced-features/scripting.md +124 -0
- package/.agents/skills/upstash/upstash-redis-js/data-structures/hashes.md +71 -0
- package/.agents/skills/upstash/upstash-redis-js/data-structures/json.md +133 -0
- package/.agents/skills/upstash/upstash-redis-js/data-structures/lists.md +72 -0
- package/.agents/skills/upstash/upstash-redis-js/data-structures/sets.md +90 -0
- package/.agents/skills/upstash/upstash-redis-js/data-structures/sorted-sets.md +126 -0
- package/.agents/skills/upstash/upstash-redis-js/data-structures/streams.md +196 -0
- package/.agents/skills/upstash/upstash-redis-js/data-structures/strings.md +73 -0
- package/.agents/skills/upstash/upstash-redis-js/migrations/from-ioredis.md +163 -0
- package/.agents/skills/upstash/upstash-redis-js/migrations/from-redis-node.md +205 -0
- package/.agents/skills/upstash/upstash-redis-js/overview.md +183 -0
- package/.agents/skills/upstash/upstash-redis-js/patterns/caching.md +58 -0
- package/.agents/skills/upstash/upstash-redis-js/patterns/distributed-locks.md +130 -0
- package/.agents/skills/upstash/upstash-redis-js/patterns/leaderboard.md +134 -0
- package/.agents/skills/upstash/upstash-redis-js/patterns/rate-limiting.md +187 -0
- package/.agents/skills/upstash/upstash-redis-js/patterns/session-management.md +217 -0
- package/.agents/skills/upstash/upstash-redis-js/performance/batching-operations.md +76 -0
- package/.agents/skills/upstash/upstash-redis-js/performance/data-serialization.md +134 -0
- package/.agents/skills/upstash/upstash-redis-js/performance/error-handling.md +118 -0
- package/.agents/skills/upstash/upstash-redis-js/performance/pipeline-optimization.md +105 -0
- package/.agents/skills/upstash/upstash-redis-js/performance/redis-replicas.md +14 -0
- package/.agents/skills/upstash/upstash-redis-js/performance/ttl-expiration.md +32 -0
- package/.agents/skills/upstash/upstash-redis-js/search/adapters.md +99 -0
- package/.agents/skills/upstash/upstash-redis-js/search/commands/aggregating.md +234 -0
- package/.agents/skills/upstash/upstash-redis-js/search/commands/aliases.md +76 -0
- package/.agents/skills/upstash/upstash-redis-js/search/commands/index-management.md +124 -0
- package/.agents/skills/upstash/upstash-redis-js/search/commands/querying.md +315 -0
- package/.agents/skills/upstash/upstash-redis-js/search/overview.md +155 -0
- package/.agents/skills/upstash/upstash-redis-start/overview.md +71 -0
- package/.agents/skills/upstash/upstash-search-js/overview.md +48 -0
- package/.agents/skills/upstash/upstash-search-js/quick-start.md +158 -0
- package/.agents/skills/upstash/upstash-search-js/sdk-overview.md +158 -0
- package/.agents/skills/upstash/upstash-vector-js/features/filtering-and-metadata.md +82 -0
- package/.agents/skills/upstash/upstash-vector-js/features/index-structure.md +193 -0
- package/.agents/skills/upstash/upstash-vector-js/features/namespaces.md +32 -0
- package/.agents/skills/upstash/upstash-vector-js/overview.md +44 -0
- package/.agents/skills/upstash/upstash-vector-js/sdk-methods.md +210 -0
- package/.agents/skills/upstash/upstash-workflow-js/agents.md +248 -0
- package/.agents/skills/upstash/upstash-workflow-js/basics/client.md +180 -0
- package/.agents/skills/upstash/upstash-workflow-js/basics/context.md +230 -0
- package/.agents/skills/upstash/upstash-workflow-js/basics/serve.md +70 -0
- package/.agents/skills/upstash/upstash-workflow-js/features/flow-control.md +145 -0
- package/.agents/skills/upstash/upstash-workflow-js/features/invoke.md +97 -0
- package/.agents/skills/upstash/upstash-workflow-js/features/retries-failures-reliability.md +239 -0
- package/.agents/skills/upstash/upstash-workflow-js/features/wait-for-event.md +97 -0
- package/.agents/skills/upstash/upstash-workflow-js/features/webhooks.md +79 -0
- package/.agents/skills/upstash/upstash-workflow-js/how-to/local-dev.md +177 -0
- package/.agents/skills/upstash/upstash-workflow-js/how-to/middleware.md +166 -0
- package/.agents/skills/upstash/upstash-workflow-js/how-to/migrations.md +201 -0
- package/.agents/skills/upstash/upstash-workflow-js/how-to/realtime.md +186 -0
- package/.agents/skills/upstash/upstash-workflow-js/overview.md +55 -0
- package/.agents/skills/upstash/upstash-workflow-js/rest-api.md +156 -0
- package/.agents/skills/upstash/upstash-workflow-js/troubleshooting.md +201 -0
- package/.agents/skills/upstash-box-js/SKILL.md +248 -0
- package/.agents/skills/upstash-box-py/SKILL.md +280 -0
- package/.agents/skills/upstash-cli/SKILL.md +143 -0
- package/.agents/skills/upstash-qstash-js/SKILL.md +86 -0
- package/.agents/skills/upstash-qstash-js/advanced/callbacks.md +147 -0
- package/.agents/skills/upstash-qstash-js/advanced/deduplication.md +86 -0
- package/.agents/skills/upstash-qstash-js/advanced/dlq.md +164 -0
- package/.agents/skills/upstash-qstash-js/advanced/multi-region/summary.md +388 -0
- package/.agents/skills/upstash-qstash-js/advanced/multi-region/verify-multi-region-setup.ts +388 -0
- package/.agents/skills/upstash-qstash-js/fundamentals/local-development.md +106 -0
- package/.agents/skills/upstash-qstash-js/fundamentals/publishing-messages.md +144 -0
- package/.agents/skills/upstash-qstash-js/fundamentals/queues-and-flow-control.md +148 -0
- package/.agents/skills/upstash-qstash-js/fundamentals/schedules.md +177 -0
- package/.agents/skills/upstash-qstash-js/fundamentals/url-groups.md +127 -0
- package/.agents/skills/upstash-qstash-js/verification/platform-specific/nextjs.md +171 -0
- package/.agents/skills/upstash-qstash-js/verification/receiver.md +213 -0
- package/.agents/skills/upstash-ratelimit-js/SKILL.md +31 -0
- package/.agents/skills/upstash-ratelimit-js/algorithms.md +84 -0
- package/.agents/skills/upstash-ratelimit-js/features.md +117 -0
- package/.agents/skills/upstash-ratelimit-js/methods-getting-started.md +77 -0
- package/.agents/skills/upstash-ratelimit-js/pricing-cost.md +146 -0
- package/.agents/skills/upstash-ratelimit-js/traffic-protection.md +77 -0
- package/.agents/skills/upstash-redis-js/SKILL.md +188 -0
- package/.agents/skills/upstash-redis-js/advanced-features/auto-pipeline.md +49 -0
- package/.agents/skills/upstash-redis-js/advanced-features/pipeline-and-transactions.md +42 -0
- package/.agents/skills/upstash-redis-js/advanced-features/scripting.md +124 -0
- package/.agents/skills/upstash-redis-js/data-structures/hashes.md +71 -0
- package/.agents/skills/upstash-redis-js/data-structures/json.md +133 -0
- package/.agents/skills/upstash-redis-js/data-structures/lists.md +72 -0
- package/.agents/skills/upstash-redis-js/data-structures/sets.md +90 -0
- package/.agents/skills/upstash-redis-js/data-structures/sorted-sets.md +126 -0
- package/.agents/skills/upstash-redis-js/data-structures/streams.md +196 -0
- package/.agents/skills/upstash-redis-js/data-structures/strings.md +73 -0
- package/.agents/skills/upstash-redis-js/migrations/from-ioredis.md +163 -0
- package/.agents/skills/upstash-redis-js/migrations/from-redis-node.md +205 -0
- package/.agents/skills/upstash-redis-js/patterns/caching.md +58 -0
- package/.agents/skills/upstash-redis-js/patterns/distributed-locks.md +130 -0
- package/.agents/skills/upstash-redis-js/patterns/leaderboard.md +134 -0
- package/.agents/skills/upstash-redis-js/patterns/rate-limiting.md +187 -0
- package/.agents/skills/upstash-redis-js/patterns/session-management.md +217 -0
- package/.agents/skills/upstash-redis-js/performance/batching-operations.md +76 -0
- package/.agents/skills/upstash-redis-js/performance/data-serialization.md +134 -0
- package/.agents/skills/upstash-redis-js/performance/error-handling.md +118 -0
- package/.agents/skills/upstash-redis-js/performance/pipeline-optimization.md +105 -0
- package/.agents/skills/upstash-redis-js/performance/redis-replicas.md +14 -0
- package/.agents/skills/upstash-redis-js/performance/ttl-expiration.md +32 -0
- package/.agents/skills/upstash-redis-js/search/adapters.md +99 -0
- package/.agents/skills/upstash-redis-js/search/commands/aggregating.md +234 -0
- package/.agents/skills/upstash-redis-js/search/commands/aliases.md +76 -0
- package/.agents/skills/upstash-redis-js/search/commands/index-management.md +124 -0
- package/.agents/skills/upstash-redis-js/search/commands/querying.md +315 -0
- package/.agents/skills/upstash-redis-js/search/overview.md +155 -0
- package/.agents/skills/upstash-redis-start/SKILL.md +76 -0
- package/.agents/skills/upstash-search-js/SKILL.md +53 -0
- package/.agents/skills/upstash-search-js/quick-start.md +158 -0
- package/.agents/skills/upstash-search-js/sdk-overview.md +158 -0
- package/.agents/skills/upstash-vector-js/SKILL.md +49 -0
- package/.agents/skills/upstash-vector-js/features/filtering-and-metadata.md +82 -0
- package/.agents/skills/upstash-vector-js/features/index-structure.md +193 -0
- package/.agents/skills/upstash-vector-js/features/namespaces.md +32 -0
- package/.agents/skills/upstash-vector-js/sdk-methods.md +210 -0
- package/.agents/skills/upstash-workflow-js/SKILL.md +60 -0
- package/.agents/skills/upstash-workflow-js/agents.md +248 -0
- package/.agents/skills/upstash-workflow-js/basics/client.md +180 -0
- package/.agents/skills/upstash-workflow-js/basics/context.md +230 -0
- package/.agents/skills/upstash-workflow-js/basics/serve.md +70 -0
- package/.agents/skills/upstash-workflow-js/features/flow-control.md +145 -0
- package/.agents/skills/upstash-workflow-js/features/invoke.md +97 -0
- package/.agents/skills/upstash-workflow-js/features/retries-failures-reliability.md +239 -0
- package/.agents/skills/upstash-workflow-js/features/wait-for-event.md +97 -0
- package/.agents/skills/upstash-workflow-js/features/webhooks.md +79 -0
- package/.agents/skills/upstash-workflow-js/how-to/local-dev.md +177 -0
- package/.agents/skills/upstash-workflow-js/how-to/middleware.md +166 -0
- package/.agents/skills/upstash-workflow-js/how-to/migrations.md +201 -0
- package/.agents/skills/upstash-workflow-js/how-to/realtime.md +186 -0
- package/.agents/skills/upstash-workflow-js/rest-api.md +156 -0
- package/.agents/skills/upstash-workflow-js/troubleshooting.md +201 -0
- package/dist/agents/coding.agent.d.ts +185 -42
- package/dist/agents/coding.agent.d.ts.map +1 -1
- package/dist/agents/coding.agent.js +42 -5
- package/dist/agents/coding.agent.js.map +1 -1
- package/dist/agents/manager.d.ts +216 -41
- package/dist/agents/manager.d.ts.map +1 -1
- package/dist/agents/manager.js +103 -140
- package/dist/agents/manager.js.map +1 -1
- package/dist/agents/security.agent.d.ts +3 -3
- package/dist/agents/swarm/development/lead.d.ts +3 -0
- package/dist/agents/swarm/development/lead.d.ts.map +1 -0
- package/dist/agents/swarm/development/lead.js +24 -0
- package/dist/agents/swarm/development/lead.js.map +1 -0
- package/dist/agents/swarm/main.d.ts +69 -0
- package/dist/agents/swarm/main.d.ts.map +1 -1
- package/dist/agents/swarm/main.js +65 -11
- package/dist/agents/swarm/main.js.map +1 -1
- package/dist/agents/swarm/registry.d.ts +2 -1
- package/dist/agents/swarm/registry.d.ts.map +1 -1
- package/dist/agents/swarm/registry.js +225 -95
- package/dist/agents/swarm/registry.js.map +1 -1
- package/dist/cli/composer.d.ts.map +1 -1
- package/dist/cli/composer.js +85 -30
- package/dist/cli/composer.js.map +1 -1
- package/dist/cli/confirm.d.ts +2 -2
- package/dist/cli/confirm.d.ts.map +1 -1
- package/dist/cli/confirm.js +373 -4
- package/dist/cli/confirm.js.map +1 -1
- package/dist/cli/doctor.d.ts +1 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +47 -2
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/format.d.ts +4 -0
- package/dist/cli/format.d.ts.map +1 -1
- package/dist/cli/format.js +352 -65
- package/dist/cli/format.js.map +1 -1
- package/dist/cli/interactive.d.ts.map +1 -1
- package/dist/cli/interactive.js +80 -2
- package/dist/cli/interactive.js.map +1 -1
- package/dist/cli/menu.d.ts.map +1 -1
- package/dist/cli/menu.js +93 -83
- package/dist/cli/menu.js.map +1 -1
- package/dist/cli/render.d.ts.map +1 -1
- package/dist/cli/render.js +2 -1
- package/dist/cli/render.js.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +262 -27
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/swarm.d.ts.map +1 -1
- package/dist/cli/swarm.js +13 -10
- package/dist/cli/swarm.js.map +1 -1
- package/dist/cli/theme.d.ts +7 -1
- package/dist/cli/theme.d.ts.map +1 -1
- package/dist/cli/theme.js +4 -16
- package/dist/cli/theme.js.map +1 -1
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +27 -4
- package/dist/cli/update.js.map +1 -1
- package/dist/config/env.d.ts +3 -1
- package/dist/config/env.d.ts.map +1 -1
- package/dist/config/env.js +22 -2
- package/dist/config/env.js.map +1 -1
- package/dist/config/models.d.ts +1 -0
- package/dist/config/models.d.ts.map +1 -1
- package/dist/config/models.js +17 -1
- package/dist/config/models.js.map +1 -1
- package/dist/documents/pdf.d.ts.map +1 -1
- package/dist/documents/pdf.js +282 -22
- package/dist/documents/pdf.js.map +1 -1
- package/dist/documents/slides.d.ts.map +1 -1
- package/dist/documents/slides.js +160 -30
- package/dist/documents/slides.js.map +1 -1
- package/dist/index.js +73 -18
- package/dist/index.js.map +1 -1
- package/dist/memory/history.js +1 -1
- package/dist/observability/doctor.d.ts.map +1 -1
- package/dist/observability/doctor.js +3 -0
- package/dist/observability/doctor.js.map +1 -1
- package/dist/runtime/progress.d.ts +5 -1
- package/dist/runtime/progress.d.ts.map +1 -1
- package/dist/runtime/progress.js.map +1 -1
- package/dist/runtime/swarm.d.ts +1 -1
- package/dist/runtime/swarm.d.ts.map +1 -1
- package/dist/runtime/swarm.js +19 -3
- package/dist/runtime/swarm.js.map +1 -1
- package/dist/runtime/tool-utils.d.ts +2 -0
- package/dist/runtime/tool-utils.d.ts.map +1 -1
- package/dist/runtime/tool-utils.js +91 -0
- package/dist/runtime/tool-utils.js.map +1 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/skills/loader.d.ts.map +1 -1
- package/dist/skills/loader.js +16 -0
- package/dist/skills/loader.js.map +1 -1
- package/dist/test-call.d.ts +2 -0
- package/dist/test-call.d.ts.map +1 -0
- package/dist/test-call.js +29 -0
- package/dist/test-call.js.map +1 -0
- package/dist/test-manager-call.d.ts +2 -0
- package/dist/test-manager-call.d.ts.map +1 -0
- package/dist/test-manager-call.js +138 -0
- package/dist/test-manager-call.js.map +1 -0
- package/dist/test-manager-filtered.d.ts +2 -0
- package/dist/test-manager-filtered.d.ts.map +1 -0
- package/dist/test-manager-filtered.js +130 -0
- package/dist/test-manager-filtered.js.map +1 -0
- package/dist/test-mcp-call.d.ts +2 -0
- package/dist/test-mcp-call.d.ts.map +1 -0
- package/dist/test-mcp-call.js +103 -0
- package/dist/test-mcp-call.js.map +1 -0
- package/dist/tools/composio.tool.d.ts +1 -1
- package/dist/tools/composio.tool.d.ts.map +1 -1
- package/dist/tools/composio.tool.js +7 -16
- package/dist/tools/composio.tool.js.map +1 -1
- package/dist/tools/daytona-browser.tool.js +1 -1
- package/dist/tools/daytona-browser.tool.js.map +1 -1
- package/dist/tools/executive.tool.d.ts +40 -0
- package/dist/tools/executive.tool.d.ts.map +1 -0
- package/dist/tools/executive.tool.js +74 -0
- package/dist/tools/executive.tool.js.map +1 -0
- package/dist/tools/filesystem.tool.d.ts +183 -40
- package/dist/tools/filesystem.tool.d.ts.map +1 -1
- package/dist/tools/filesystem.tool.js +564 -111
- package/dist/tools/filesystem.tool.js.map +1 -1
- package/dist/tools/mcp.tool.d.ts +56 -0
- package/dist/tools/mcp.tool.d.ts.map +1 -0
- package/dist/tools/mcp.tool.js +285 -0
- package/dist/tools/mcp.tool.js.map +1 -0
- package/dist/tools/osint.tool.d.ts +4 -4
- package/dist/tools/pentest.tool.d.ts +2 -2
- package/dist/tools/setup-assistant.tool.d.ts +1 -1
- package/dist/tools/setup-assistant.tool.js +1 -1
- package/dist/tools/setup-assistant.tool.js.map +1 -1
- package/dist/workspace/paths.d.ts +1 -0
- package/dist/workspace/paths.d.ts.map +1 -1
- package/dist/workspace/paths.js +3 -4
- package/dist/workspace/paths.js.map +1 -1
- package/package.json +8 -4
- package/scripts/postinstall.mjs +19 -4
- package/scripts/release-github.mjs +11 -11
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# Index Management
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Create, inspect, and drop search indexes. Wait for indexing to complete after data changes. Indexes automatically track Redis keys matching a specified prefix.
|
|
6
|
+
|
|
7
|
+
## Good For
|
|
8
|
+
|
|
9
|
+
- Creating indexes over existing or new Redis data
|
|
10
|
+
- Inspecting index schema and configuration
|
|
11
|
+
- Rebuilding or dropping indexes
|
|
12
|
+
- Ensuring data consistency after bulk writes
|
|
13
|
+
|
|
14
|
+
## Examples
|
|
15
|
+
|
|
16
|
+
### Create an Index
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { Redis, s } from "@upstash/redis";
|
|
20
|
+
|
|
21
|
+
const redis = Redis.fromEnv();
|
|
22
|
+
|
|
23
|
+
// JSON index with nested schema
|
|
24
|
+
const index = await redis.search.createIndex({
|
|
25
|
+
name: "products",
|
|
26
|
+
prefix: "product:",
|
|
27
|
+
dataType: "json",
|
|
28
|
+
schema: s.object({
|
|
29
|
+
name: s.string(),
|
|
30
|
+
price: s.number("F64"),
|
|
31
|
+
metadata: s.object({
|
|
32
|
+
brand: s.facet(),
|
|
33
|
+
tags: s.keyword(),
|
|
34
|
+
}),
|
|
35
|
+
}),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Hash index (flat schema only)
|
|
39
|
+
const hashIndex = await redis.search.createIndex({
|
|
40
|
+
name: "sessions",
|
|
41
|
+
prefix: "session:",
|
|
42
|
+
dataType: "hash",
|
|
43
|
+
schema: {
|
|
44
|
+
userId: { type: "TEXT" as const },
|
|
45
|
+
lastActive: { type: "DATE" as const },
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Create with Options
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
const index = await redis.search.createIndex({
|
|
54
|
+
name: "articles",
|
|
55
|
+
prefix: ["article:", "post:"], // multiple prefixes
|
|
56
|
+
dataType: "json",
|
|
57
|
+
language: "english", // stemming language
|
|
58
|
+
skipInitialScan: false, // scan existing keys (default)
|
|
59
|
+
existsOk: true, // don't error if index already exists
|
|
60
|
+
schema: s.object({
|
|
61
|
+
title: s.string(),
|
|
62
|
+
body: s.string().noStem(),
|
|
63
|
+
publishedAt: s.date().fast(),
|
|
64
|
+
}),
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Get a Reference to an Existing Index
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
// If you already created the index and just need a reference
|
|
72
|
+
const index = redis.search.index({
|
|
73
|
+
name: "products",
|
|
74
|
+
schema: s.object({
|
|
75
|
+
name: s.string(),
|
|
76
|
+
price: s.number("F64"),
|
|
77
|
+
}),
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Without schema (untyped - no filter/select type safety)
|
|
81
|
+
const untypedIndex = redis.search.index({ name: "products" });
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Describe an Index
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
const description = await index.describe();
|
|
88
|
+
// {
|
|
89
|
+
// name: "products",
|
|
90
|
+
// dataType: "json",
|
|
91
|
+
// prefixes: ["product:"],
|
|
92
|
+
// language: "english",
|
|
93
|
+
// schema: { name: { type: "TEXT" }, price: { type: "F64", fast: true } }
|
|
94
|
+
// }
|
|
95
|
+
|
|
96
|
+
// Returns null if index doesn't exist
|
|
97
|
+
const missing = await redis.search.index({ name: "nonexistent" }).describe();
|
|
98
|
+
// null
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Wait for Indexing
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// After inserting/updating/deleting data, wait for index to catch up
|
|
105
|
+
await redis.json.set("product:1", "$", { name: "Laptop", price: 999 });
|
|
106
|
+
await redis.json.set("product:2", "$", { name: "Mouse", price: 29 });
|
|
107
|
+
await redis.json.set("product:3", "$", { name: "Keyboard", price: 79 });
|
|
108
|
+
|
|
109
|
+
await index.waitIndexing(); // blocks until all pending docs are indexed
|
|
110
|
+
|
|
111
|
+
// Queries now reflect the latest data
|
|
112
|
+
const results = await index.query({ filter: { name: { $eq: "Laptop" } } });
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Drop an Index
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
const result = await index.drop();
|
|
119
|
+
// 1 if dropped, 0 if index didn't exist
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Supported Languages
|
|
123
|
+
|
|
124
|
+
For stemming: `english`, `french`, `spanish`, `portuguese`, `italian`, `german`, `dutch`, `swedish`, `norwegian`, `danish`, `finnish`, `hungarian`, `russian`, `romanian`, `turkish`, `arabic`, `chinese`, `japanese`
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
# Querying & Counting
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Query documents from a search index using type-safe filters with support for pagination, sorting, field selection, scoring, and highlighting. Count matching documents efficiently without returning results.
|
|
6
|
+
|
|
7
|
+
## Good For
|
|
8
|
+
|
|
9
|
+
- Full-text search with fuzzy matching and phrase queries
|
|
10
|
+
- Filtering by numeric ranges, dates, booleans, keywords
|
|
11
|
+
- Paginated results with sorting
|
|
12
|
+
- Highlighting search terms in results
|
|
13
|
+
- Counting documents matching a filter
|
|
14
|
+
|
|
15
|
+
## Examples
|
|
16
|
+
|
|
17
|
+
### Basic Query
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { Redis, s } from "@upstash/redis";
|
|
21
|
+
|
|
22
|
+
const redis = Redis.fromEnv();
|
|
23
|
+
|
|
24
|
+
const index = await redis.search.createIndex({
|
|
25
|
+
name: "products",
|
|
26
|
+
prefix: "product:",
|
|
27
|
+
dataType: "json",
|
|
28
|
+
schema: s.object({
|
|
29
|
+
name: s.string(),
|
|
30
|
+
price: s.number("F64"),
|
|
31
|
+
category: s.keyword(),
|
|
32
|
+
inStock: s.boolean(),
|
|
33
|
+
}),
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Insert data
|
|
37
|
+
await redis.json.set("product:1", "$", {
|
|
38
|
+
name: "Gaming Laptop",
|
|
39
|
+
price: 1299.99,
|
|
40
|
+
category: "electronics",
|
|
41
|
+
inStock: true,
|
|
42
|
+
});
|
|
43
|
+
await redis.json.set("product:2", "$", {
|
|
44
|
+
name: "Wireless Mouse",
|
|
45
|
+
price: 29.99,
|
|
46
|
+
category: "electronics",
|
|
47
|
+
inStock: true,
|
|
48
|
+
});
|
|
49
|
+
await redis.json.set("product:3", "$", {
|
|
50
|
+
name: "Laptop Stand",
|
|
51
|
+
price: 49.99,
|
|
52
|
+
category: "accessories",
|
|
53
|
+
inStock: false,
|
|
54
|
+
});
|
|
55
|
+
await index.waitIndexing();
|
|
56
|
+
|
|
57
|
+
// Query with filter and return data
|
|
58
|
+
const results = await index.query({
|
|
59
|
+
filter: { category: { $eq: "electronics" } },
|
|
60
|
+
select: { name: true, price: true },
|
|
61
|
+
});
|
|
62
|
+
// [
|
|
63
|
+
// { key: "product:1", score: ..., data: { name: "Gaming Laptop", price: 1299.99 } },
|
|
64
|
+
// { key: "product:2", score: ..., data: { name: "Wireless Mouse", price: 29.99 } },
|
|
65
|
+
// ]
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Keys Only (No Data)
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
// Set select to {}
|
|
72
|
+
const keysOnly = await index.query({
|
|
73
|
+
filter: { inStock: { $eq: true } },
|
|
74
|
+
select: {},
|
|
75
|
+
});
|
|
76
|
+
// [{ key: "product:1", score: ... }, { key: "product:2", score: ... }]
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Pagination
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
const page2 = await index.query({
|
|
83
|
+
filter: { category: { $eq: "electronics" } },
|
|
84
|
+
select: { name: true },
|
|
85
|
+
limit: 10,
|
|
86
|
+
offset: 10, // skip first 10 results
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Sorting
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
const cheapest = await index.query({
|
|
94
|
+
filter: { inStock: { $eq: true } },
|
|
95
|
+
select: { name: true, price: true },
|
|
96
|
+
orderBy: { price: "ASC" },
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Score Function
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
// Rank by relevance with a score modifier
|
|
104
|
+
const results = await index.query({
|
|
105
|
+
filter: { name: { $eq: "laptop" } },
|
|
106
|
+
select: { name: true },
|
|
107
|
+
scoreFunc: { field: "name", modifier: "log1p" },
|
|
108
|
+
});
|
|
109
|
+
// Available modifiers: log, log1p, log2p, ln, ln1p, ln2p, square, sqrt, reciprocal, none
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Highlighting
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
const highlighted = await index.query({
|
|
116
|
+
filter: { name: { $eq: "laptop" } },
|
|
117
|
+
select: { name: true },
|
|
118
|
+
highlight: {
|
|
119
|
+
fields: ["name"],
|
|
120
|
+
preTag: "<mark>", // optional, default <em>
|
|
121
|
+
postTag: "</mark>", // optional, default </em>
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
// data.name: "Gaming <mark>Laptop</mark>"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Filter Operators
|
|
128
|
+
|
|
129
|
+
### Text Field Filters
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
// Exact substring match
|
|
133
|
+
{ name: { $eq: "laptop" } }
|
|
134
|
+
|
|
135
|
+
// Multiple values (OR)
|
|
136
|
+
{ name: { $in: ["laptop", "tablet"] } }
|
|
137
|
+
|
|
138
|
+
// Fuzzy matching (typo tolerance)
|
|
139
|
+
{ name: { $fuzzy: { value: "lapto", distance: 1 } } }
|
|
140
|
+
|
|
141
|
+
// Phrase matching (adjacent words with tolerance)
|
|
142
|
+
{ name: { $phrase: { value: "gaming laptop", slop: 1 } } }
|
|
143
|
+
|
|
144
|
+
// Regex pattern
|
|
145
|
+
{ name: { $regex: "lap.*" } }
|
|
146
|
+
|
|
147
|
+
// Smart matching (automatic fuzzy + phrase + term)
|
|
148
|
+
{ name: { $smart: "gaming laptop" } }
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Numeric Field Filters
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
// Exact value
|
|
155
|
+
{ price: { $eq: 29.99 } }
|
|
156
|
+
|
|
157
|
+
// Range
|
|
158
|
+
{ price: { $gte: 10, $lte: 100 } }
|
|
159
|
+
|
|
160
|
+
// Greater/less than
|
|
161
|
+
{ price: { $gt: 50 } }
|
|
162
|
+
{ stock: { $lt: 10 } }
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Boolean Field Filters
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
{
|
|
169
|
+
inStock: {
|
|
170
|
+
$eq: true;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
{
|
|
174
|
+
inStock: {
|
|
175
|
+
$in: [true, false];
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Date Field Filters
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
{ createdAt: { $gte: "2024-01-01", $lt: "2025-01-01" } }
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Keyword Field Filters
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
// Exact match
|
|
190
|
+
{ category: { $eq: "electronics" } }
|
|
191
|
+
|
|
192
|
+
// Multiple values
|
|
193
|
+
{ category: { $in: ["electronics", "accessories"] } }
|
|
194
|
+
|
|
195
|
+
// Lexicographic range
|
|
196
|
+
{ category: { $gte: "a", $lt: "m" } }
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Facet Field Filters
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
{
|
|
203
|
+
brand: {
|
|
204
|
+
$eq: "Apple";
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
{
|
|
208
|
+
brand: {
|
|
209
|
+
$in: ["Apple", "Samsung"];
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Boolean Operators
|
|
215
|
+
|
|
216
|
+
Combine filters using boolean operators:
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
// AND - all conditions must match
|
|
220
|
+
{
|
|
221
|
+
$and: [
|
|
222
|
+
{ category: { $eq: "electronics" } },
|
|
223
|
+
{ price: { $lte: 500 } },
|
|
224
|
+
]
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// OR - any condition matches
|
|
228
|
+
{
|
|
229
|
+
$or: [
|
|
230
|
+
{ category: { $eq: "electronics" } },
|
|
231
|
+
{ category: { $eq: "accessories" } },
|
|
232
|
+
]
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// MUST + MUST NOT - require some, exclude others
|
|
236
|
+
{
|
|
237
|
+
$must: [{ category: { $eq: "electronics" } }],
|
|
238
|
+
$mustNot: [{ inStock: { $eq: false } }],
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// MUST + SHOULD - required conditions + optional boosters
|
|
242
|
+
{
|
|
243
|
+
$must: [{ category: { $eq: "electronics" } }],
|
|
244
|
+
$should: [{ name: { $eq: "premium" } }], // boosts score if matched
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// SHOULD alone - at least one must match (acts like OR)
|
|
248
|
+
{
|
|
249
|
+
$should: [
|
|
250
|
+
{ name: { $eq: "laptop" } },
|
|
251
|
+
{ name: { $eq: "tablet" } },
|
|
252
|
+
]
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Common mistake: `$should` next to `$must` does NOT filter
|
|
257
|
+
|
|
258
|
+
Adding `$must` silently turns sibling `$should` clauses into **score boosters only** —
|
|
259
|
+
documents are *not* required to match them. Membership is decided entirely by `$must`,
|
|
260
|
+
so the query "always finds something" even for nonsense terms (matches come back, just
|
|
261
|
+
with a low score). This is the most common search bug.
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
// ❌ WRONG: the term only boosts; every in-stock doc still matches via $must,
|
|
265
|
+
// so a nonsensical searchTerm still returns results (with low scores).
|
|
266
|
+
{
|
|
267
|
+
$must: { inStock: { $eq: true } },
|
|
268
|
+
$should: [
|
|
269
|
+
{ name: { $smart: searchTerm }, $boost: 10 },
|
|
270
|
+
{ description: { $smart: searchTerm }, $boost: 5 },
|
|
271
|
+
],
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// ✅ RIGHT: require a match in at least one field by nesting the OR ($should
|
|
275
|
+
// alone acts as OR) inside $must. $boost still ranks name above description.
|
|
276
|
+
{
|
|
277
|
+
$must: [
|
|
278
|
+
{ inStock: { $eq: true } },
|
|
279
|
+
{
|
|
280
|
+
$should: [
|
|
281
|
+
{ name: { $smart: searchTerm }, $boost: 10 },
|
|
282
|
+
{ description: { $smart: searchTerm }, $boost: 5 },
|
|
283
|
+
],
|
|
284
|
+
},
|
|
285
|
+
],
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
> There is no minimum-score / cutoff option on `query()`. Don't filter by the returned
|
|
290
|
+
> `score` (scores are relative and shift with `$boost`, so a fixed threshold isn't
|
|
291
|
+
> reliable) — instead make the term required as above so non-matches are excluded.
|
|
292
|
+
|
|
293
|
+
### Boosting
|
|
294
|
+
|
|
295
|
+
Boost the score of specific conditions:
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
{
|
|
299
|
+
$must: [
|
|
300
|
+
{ name: { $eq: "laptop", $boost: 2.0 } }, // double the score weight
|
|
301
|
+
{ category: { $eq: "electronics", $boost: 0.5 } },
|
|
302
|
+
];
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Counting
|
|
307
|
+
|
|
308
|
+
Count matching documents without returning them:
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
const { count } = await index.count({
|
|
312
|
+
filter: { category: { $eq: "electronics" } },
|
|
313
|
+
});
|
|
314
|
+
// count: 2
|
|
315
|
+
```
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Redis Search
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Redis Search is a full-text search and secondary indexing extension for Upstash Redis. It provides powerful APIs for querying, filtering, and aggregating data stored in Redis keys. Built on Tantivy, it supports text search with stemming, fuzzy matching, faceted navigation, and complex aggregations.
|
|
6
|
+
|
|
7
|
+
## Good For
|
|
8
|
+
|
|
9
|
+
- Full-text search over Redis data (strings, JSON, hashes)
|
|
10
|
+
- Filtering and sorting with type-safe queries
|
|
11
|
+
- Aggregations and analytics (averages, histograms, facets)
|
|
12
|
+
- Autocomplete and typo-tolerant search
|
|
13
|
+
- Faceted navigation (e-commerce categories, filters)
|
|
14
|
+
|
|
15
|
+
## Packages
|
|
16
|
+
|
|
17
|
+
- `@upstash/redis` - The primary SDK. Access search via `redis.search` (works over HTTP)
|
|
18
|
+
- `@upstash/search-redis` - Adapter for the `redis` (node-redis) TCP client
|
|
19
|
+
- `@upstash/search-ioredis` - Adapter for the `ioredis` TCP client
|
|
20
|
+
|
|
21
|
+
All three packages expose the same search API. See [adapters.md](./adapters.md) for TCP client setup.
|
|
22
|
+
|
|
23
|
+
## Schema
|
|
24
|
+
|
|
25
|
+
Schemas define which fields are indexed and how. Use the `s` schema builder for type-safe definitions:
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { Redis, s } from "@upstash/redis";
|
|
29
|
+
|
|
30
|
+
const redis = Redis.fromEnv();
|
|
31
|
+
|
|
32
|
+
const index = await redis.search.createIndex({
|
|
33
|
+
name: "products",
|
|
34
|
+
prefix: "product:",
|
|
35
|
+
dataType: "json",
|
|
36
|
+
schema: s.object({
|
|
37
|
+
name: s.string(), // TEXT - full-text searchable
|
|
38
|
+
description: s.string().noStem(), // TEXT without stemming
|
|
39
|
+
sku: s.string().noTokenize(), // TEXT stored as-is (no splitting)
|
|
40
|
+
price: s.number("F64"), // floating point number
|
|
41
|
+
stock: s.number("U64"), // unsigned 64-bit integer
|
|
42
|
+
inStock: s.boolean(), // boolean
|
|
43
|
+
createdAt: s.date(), // date
|
|
44
|
+
category: s.keyword(), // exact-match keyword
|
|
45
|
+
brand: s.facet(), // facet for aggregations
|
|
46
|
+
}),
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Field Types
|
|
51
|
+
|
|
52
|
+
| Builder | Redis Type | TypeScript | Use Case |
|
|
53
|
+
| -------------- | ----------- | ---------- | -------------------------------- |
|
|
54
|
+
| `s.string()` | TEXT | `string` | Full-text searchable text |
|
|
55
|
+
| `s.number()` | F64/U64/I64 | `number` | Numeric values, ranges |
|
|
56
|
+
| `s.boolean()` | BOOL | `boolean` | True/false filtering |
|
|
57
|
+
| `s.date()` | DATE | `string` | Date range queries |
|
|
58
|
+
| `s.keyword()` | KEYWORD | `string` | Exact match, lexicographic range |
|
|
59
|
+
| `s.facet()` | FACET | `string` | Faceted aggregations |
|
|
60
|
+
| `s.object({})` | (nested) | `object` | Nested field groups |
|
|
61
|
+
|
|
62
|
+
### Field Options
|
|
63
|
+
|
|
64
|
+
- `.noTokenize()` - (TEXT only) Don't split on whitespace/punctuation. Use for SKUs, URLs, emails
|
|
65
|
+
- `.noStem()` - (TEXT only) Don't reduce words to stems. Use for brand names, proper nouns
|
|
66
|
+
- `.fast()` - (BOOL, DATE) Enable fast filtering
|
|
67
|
+
- `.from("fieldName")` - Map index field to a different field name in the stored data
|
|
68
|
+
|
|
69
|
+
### Data Types
|
|
70
|
+
|
|
71
|
+
- `"json"` - Index JSON documents stored with `redis.json.set()` or `redis.set()`. Supports nested schemas with `s.object()`
|
|
72
|
+
- `"string"` - Index JSON strings stored with `redis.set()`. Supports nested schemas
|
|
73
|
+
- `"hash"` - Index Redis hashes stored with `redis.hset()`. Flat schemas only (no nesting)
|
|
74
|
+
|
|
75
|
+
## Commands
|
|
76
|
+
|
|
77
|
+
For detailed usage of each command category, see:
|
|
78
|
+
|
|
79
|
+
- [commands/querying.md](./commands/querying.md) - Query and count documents with filters, pagination, sorting, highlighting
|
|
80
|
+
- [commands/aggregating.md](./commands/aggregating.md) - Aggregations: metrics ($avg, $sum, $min, $max), buckets ($terms, $range, $histogram), facets
|
|
81
|
+
- [commands/index-management.md](./commands/index-management.md) - Create, describe, drop indexes; wait for indexing
|
|
82
|
+
- [commands/aliases.md](./commands/aliases.md) - Manage index aliases for zero-downtime reindexing
|
|
83
|
+
|
|
84
|
+
## Pitfalls
|
|
85
|
+
|
|
86
|
+
### Data is upserted with regular Redis commands, not through search
|
|
87
|
+
|
|
88
|
+
There is no `index.upsert()` or `index.add()` method. You store data using standard Redis commands (`set`, `json.set`, `hset`), and the search index automatically picks up keys matching its prefix.
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
// Create the index
|
|
92
|
+
const index = await redis.search.createIndex({
|
|
93
|
+
name: "users",
|
|
94
|
+
prefix: "user:",
|
|
95
|
+
dataType: "json",
|
|
96
|
+
schema: s.object({ name: s.string(), age: s.number("U64") }),
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Upsert data with regular Redis commands
|
|
100
|
+
await redis.json.set("user:1", "$", { name: "Alice", age: 30 });
|
|
101
|
+
await redis.json.set("user:2", "$", { name: "Bob", age: 25 });
|
|
102
|
+
|
|
103
|
+
// Wait for the index to process the new data
|
|
104
|
+
await index.waitIndexing();
|
|
105
|
+
|
|
106
|
+
// Now you can query
|
|
107
|
+
const results = await index.query({
|
|
108
|
+
filter: { name: { $eq: "Alice" } },
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Always call waitIndexing after data changes
|
|
113
|
+
|
|
114
|
+
Index updates are batched. After upserting or deleting data, the index may not immediately reflect the changes. Call `waitIndexing()` to block until all pending documents are processed.
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// Batch upsert many documents
|
|
118
|
+
for (const product of products) {
|
|
119
|
+
await redis.json.set(`product:${product.id}`, "$", product);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Call waitIndexing ONCE after all upserts (not after each one)
|
|
123
|
+
await index.waitIndexing();
|
|
124
|
+
|
|
125
|
+
// Now queries will return up-to-date results
|
|
126
|
+
const results = await index.query({ filter: { category: { $eq: "electronics" } } });
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Tokenization splits text at word boundaries
|
|
130
|
+
|
|
131
|
+
TEXT fields are tokenized by default: `"hello-world"` becomes `["hello", "world"]`. An `$eq` filter for `"hello-world"` matches because it finds the substring. But if you need exact matching of the full string (e.g., SKUs, URLs), use `.noTokenize()`.
|
|
132
|
+
|
|
133
|
+
### Stemming reduces words to roots
|
|
134
|
+
|
|
135
|
+
By default, TEXT fields apply language-specific stemming: `"running"` is stored as `"run"`. This means `$regex` patterns won't match the original form. Disable with `.noStem()` for brand names or when you need exact word forms.
|
|
136
|
+
|
|
137
|
+
### $mustNot cannot be used alone
|
|
138
|
+
|
|
139
|
+
`$mustNot` filters only exclude documents. Using `$mustNot` alone returns no results. Always combine it with `$must` or `$should`:
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
// Won't work - returns nothing
|
|
143
|
+
{ $mustNot: [{ status: { $eq: "archived" } }] }
|
|
144
|
+
|
|
145
|
+
// Correct - exclude within a broader match
|
|
146
|
+
{ $must: [{ category: { $eq: "electronics" } }], $mustNot: [{ status: { $eq: "archived" } }] }
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### SCOREFUNC and ORDERBY are mutually exclusive
|
|
150
|
+
|
|
151
|
+
You cannot use `scoreFunc` and `orderBy` in the same query. Use `orderBy` for deterministic sorting, `scoreFunc` for relevance-based ranking.
|
|
152
|
+
|
|
153
|
+
## Resources
|
|
154
|
+
|
|
155
|
+
- [Upstash Redis Search documentation](https://upstash.com/docs/redis/search)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: upstash-redis-start
|
|
3
|
+
description: Provision a zero-config, no-signup Upstash Redis database for an AI agent via a single POST to `https://upstash.com/start-redis`. Use when an agent needs scratch Redis for short-term memory, conversation history, sub-agent work queues, or ranked recall and the user has not provided credentials. The database lives 3 days unless the user claims it.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Upstash Redis for Agents (`start-redis`)
|
|
7
|
+
|
|
8
|
+
A zero-config Redis database for AI agents — **no signup, no UI, no SDK setup**. One HTTP request returns a working endpoint + token. Databases live for **3 days** unless the user claims them.
|
|
9
|
+
|
|
10
|
+
Use this when:
|
|
11
|
+
- The agent needs Redis right now and the user has not given you credentials.
|
|
12
|
+
- You want short-term memory across tool calls, conversation history, a sub-agent work queue, or recent-first ranked recall.
|
|
13
|
+
|
|
14
|
+
Do **not** use this for: production workloads, anything tied to a user account, or anything storing PII / secrets / production credentials. The database is temporary and unauthenticated until claimed.
|
|
15
|
+
|
|
16
|
+
## Create or re-fetch a database
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Generate a fresh UUIDv4 yourself, then POST it as the Idempotency-Key.
|
|
20
|
+
# The UUIDv4 you send becomes the database id.
|
|
21
|
+
curl -X POST -H "Idempotency-Key: <uuidv4>" https://upstash.com/start-redis
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- Sending your own UUIDv4 makes the first call **retry-safe** — if the response is lost, retrying with the same UUID returns the same database instead of minting a duplicate.
|
|
25
|
+
- Re-POST with the same `Idempotency-Key` to **re-fetch credentials** for an existing database.
|
|
26
|
+
- The header is optional. Omit it to mint a new database with a server-generated id (returned in the response — re-fetch later by passing that id back as `Idempotency-Key`). Only UUIDv4 is accepted.
|
|
27
|
+
|
|
28
|
+
The response is markdown containing:
|
|
29
|
+
- `Database ID`, `Endpoint`, `Token`
|
|
30
|
+
- `Metrics` URL (JSON: uptime, commands, keys, throughput, memory, bandwidth)
|
|
31
|
+
- `Expires` date
|
|
32
|
+
- `Console URL` to share with the user (where they view usage and click **Claim** to keep the database)
|
|
33
|
+
- An inline quickstart for the body-style REST API
|
|
34
|
+
|
|
35
|
+
Parse these out of the markdown response and use them directly — there is no separate JSON envelope.
|
|
36
|
+
|
|
37
|
+
## Calling the database (body-style REST)
|
|
38
|
+
|
|
39
|
+
The returned endpoint speaks the Upstash Redis REST API. Prefer the **body-style** form: POST a JSON array as the body so you don't have to URL-encode the command.
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# SET with TTL
|
|
43
|
+
curl https://<endpoint> \
|
|
44
|
+
-H "Authorization: Bearer <token>" \
|
|
45
|
+
-d '["SET","session:abc","{\"step\":2}","EX","3600"]'
|
|
46
|
+
|
|
47
|
+
# GET
|
|
48
|
+
curl https://<endpoint> \
|
|
49
|
+
-H "Authorization: Bearer <token>" \
|
|
50
|
+
-d '["GET","session:abc"]'
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
You can also use the official SDKs against the same endpoint + token (`@upstash/redis` for TS/JS, `upstash-redis` for Python).
|
|
54
|
+
|
|
55
|
+
## Common agent patterns
|
|
56
|
+
|
|
57
|
+
| Need | Commands |
|
|
58
|
+
|------|----------|
|
|
59
|
+
| Short-term memory across tool calls in one run | `SET key value EX <ttl>` / `GET key` |
|
|
60
|
+
| Conversation / turn-by-turn log | `LPUSH chat:<user> <json>` / `LRANGE chat:<user> 0 20` |
|
|
61
|
+
| Sub-agent work queue (producer/consumer) | `LPUSH jobs <json>` / `RPOP jobs` |
|
|
62
|
+
| Ranked memory (recent-first or score-first) | `ZADD memories <score> <member>` / `ZREVRANGE memories 0 9` |
|
|
63
|
+
|
|
64
|
+
## Tell the user
|
|
65
|
+
|
|
66
|
+
After provisioning, surface the **console URL** from the response to the user. Make clear that:
|
|
67
|
+
- The database expires in 3 days.
|
|
68
|
+
- They can view usage at the console URL and click **Claim** to keep it.
|
|
69
|
+
- This is unauthenticated scratch storage — don't put secrets or PII in it.
|
|
70
|
+
|
|
71
|
+
## Reference
|
|
72
|
+
|
|
73
|
+
- Service entry point (also serves the `GET` doc): https://upstash.com/start-redis
|
|
74
|
+
- Full REST API: https://upstash.com/docs/redis/features/restapi
|
|
75
|
+
- TS/JS SDK: https://upstash.com/docs/redis/sdks/ts
|
|
76
|
+
- Python SDK: https://upstash.com/docs/redis/sdks/py
|