/querying
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.
How it fires
How this command gets triggered: by you, by Claude, or both.
- Fires itselfClaude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/querying
Context preview
What this command does when you run it.
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.
Command definition
querying.mdQuerying & Counting
Overview
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.
Good For
- Full-text search with fuzzy matching and phrase queries
- Filtering by numeric ranges, dates, booleans, keywords
- Paginated results with sorting
- Highlighting search terms in results
- Counting documents matching a filter
Examples
Basic Query
import { Redis, s } from "@upstash/redis";
const redis = Redis.fromEnv();
const index = await redis.search.createIndex({
name: "products",
prefix: "product:",
dataType: "json",
schema: s.object({
name: s.string(),
price: s.number("F64"),
category: s.keyword(),
inStock: s.boolean(),
}),
});
// Insert data
await redis.json.set("product:1", "$", {
name: "Gaming Laptop",
price: 1299.99,
category: "electronics",
inStock: true,
});
await redis.json.set("product:2", "$", {
name: "Wireless Mouse",
price: 29.99,
category: "electronics",
inStock: true,
});
await redis.json.set("product:3", "$", {
name: "Laptop Stand",
price: 49.99,
category: "accessories",
inStock: false,
});
await index.waitIndexing();
// Query with filter and return data
const results = await index.query({
filter: { category: { $eq: "electronics" } },
select: { name: true, price: true },
});
// [
// { key: "product:1", score: ..., data: { name: "Gaming Laptop", price: 1299.99 } },
// { key: "product:2", score: ..., data: { name: "Wireless Mouse", price: 29.99 } },
// ]Keys Only (No Data)
// Set select to {}
const keysOnly = await index.query({
filter: { inStock: { $eq: true } },
select: {},
});
// [{ key: "product:1", score: ... }, { key: "product:2", score: ... }]Pagination
const page2 = await index.query({
filter: { category: { $eq: "electronics" } },
select: { name: true },
limit: 10,
offset: 10, // skip first 10 results
});Sorting
const cheapest = await index.query({
filter: { inStock: { $eq: true } },
select: { name: true, price: true },
orderBy: { price: "ASC" },
});Score Function
// Rank by relevance with a score modifier
const results = await index.query({
filter: { name: { $eq: "laptop" } },
select: { name: true },
scoreFunc: { field: "name", modifier: "LOG1P" },
});
// Available modifiers: LOG, LOG1P, LOG2P, LN, LN1P, LN2P, SQRT, SQUARE, RECIPROCAL, NONEHighlighting
const highlighted = await index.query({
filter: { name: { $eq: "laptop" } },
select: { name: true },
highlight: {
fields: ["name"],
preTag: "<mark>", // optional, default <em>
postTag: "</mark>", // optional, default </em>
},
});
// data.name: "Gaming <mark>Laptop</mark>"Filter Operators
Text Field Filters
// Exact substring match
{ name: { $eq: "laptop" } }
// Multiple values (OR)
{ name: { $in: ["laptop", "tablet"] } }
// Fuzzy matching (typo tolerance)
{ name: { $fuzzy: { term: "lapto", distance: 1 } } }
// Phrase matching (adjacent words with tolerance)
{ name: { $phrase: { text: "gaming laptop", slop: 1 } } }
// Regex pattern
{ name: { $regex: "lap.*" } }
// Smart matching (automatic fuzzy + phrase + term)
{ name: { $smart: "gaming laptop" } }Numeric Field Filters
// Exact value
{ price: { $eq: 29.99 } }
// Range
{ price: { $gte: 10, $lte: 100 } }
// Greater/less than
{ price: { $gt: 50 } }
{ stock: { $lt: 10 } }Boolean Field Filters
{
inStock: {
$eq: true;
}
}
{
inStock: {
$in: [true, false];
}
}Date Field Filters
{ createdAt: { $gte: "2024-01-01", $lt: "2025-01-01" } }Keyword Field Filters
// Exact match
{ category: { $eq: "electronics" } }
// Multiple values
{ category: { $in: ["electronics", "accessories"] } }
// Lexicographic range
{ category: { $gte: "a", $lt: "m" } }Facet Field Filters
{
brand: {
$eq: "Apple";
}
}
{
brand: {
$in: ["Apple", "Samsung"];
}
}Boolean Operators
Combine filters using boolean operators:
// AND - all conditions must match
{
$and: [
{ category: { $eq: "electronics" } },
{ price: { $lte: 500 } },
]
}
// OR - any condition matches
{
$or: [
{ category: { $eq: "electronics" } },
{ category: { $eq: "accessories" } },
]
}
// MUST + MUST NOT - require some, exclude others
{
$must: [{ category: { $eq: "electronics" } }],
$mustNot: [{ inStock: { $eq: false } }],
}
// MUST + SHOULD - required conditions + optional boosters
{
$must: [{ category: { $eq: "electronics" } }],
$should: [{ name: { $eq: "premium" } }], // boosts score if matched
}
// SHOULD alone - at least one must match (acts like OR)
{
$should: [
{ name: { $eq: "laptop" } },
{ name: { $eq: "tablet" } },
]
}Boosting
Boost the score of specific conditions:
{
$must: [
{ name: { $eq: "laptop", $boost: 2.0 } }, // double the score weight
{ category: { $eq: "electronics", $boost: 0.5 } },
];
}Counting
Count matching documents without returning them:
const { count } = await index.count({
filter: { category: { $eq: "electronics" } },
});
// count: 2Read more
Querying & Counting
Overview
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.
Good For
- Full-text search with fuzzy matching and phrase queries
- Filtering by numeric ranges, dates, booleans, keywords
- Paginated results with sorting
- Highlighting search terms in results
- Counting documents matching a filter
Examples
Basic Query
import { Redis, s } from "@upstash/redis";
const redis = Redis.fromEnv();
const index = await redis.search.createIndex({
name: "products",
prefix: "product:",
dataType: "json",
schema: s.object({
name: s.string(),
price: s.number("F64"),
category: s.keyword(),
inStock: s.boolean(),
}),
});
// Insert data
await redis.json.set("product:1", "$", {
name: "Gaming Laptop",
price: 1299.99,
category: "electronics",
inStock: true,
});
await redis.json.set("product:2", "$", {
name: "Wireless Mouse",
price: 29.99,
category: "electronics",
inStock: true,
});
await redis.json.set("product:3", "$", {
name: "Laptop Stand",
price: 49.99,
category: "accessories",
inStock: false,
});
await index.waitIndexing();
// Query with filter and return data
const results = await index.query({
filter: { category: { $eq: "electronics" } },
select: { name: true, price: true },
});
// [
// { key: "product:1", score: ..., data: { name: "Gaming Laptop", price: 1299.99 } },
// { key: "product:2", score: ..., data: { name: "Wireless Mouse", price: 29.99 } },
// ]Keys Only (No Data)
// Set select to {}
const keysOnly = await index.query({
filter: { inStock: { $eq: true } },
select: {},
});
// [{ key: "product:1", score: ... }, { key: "product:2", score: ... }]Pagination
const page2 = await index.query({
filter: { category: { $eq: "electronics" } },
select: { name: true },
limit: 10,
offset: 10, // skip first 10 results
});Sorting
const cheapest = await index.query({
filter: { inStock: { $eq: true } },
select: { name: true, price: true },
orderBy: { price: "ASC" },
});Score Function
// Rank by relevance with a score modifier
const results = await index.query({
filter: { name: { $eq: "laptop" } },
select: { name: true },
scoreFunc: { field: "name", modifier: "LOG1P" },
});
// Available modifiers: LOG, LOG1P, LOG2P, LN, LN1P, LN2P, SQRT, SQUARE, RECIPROCAL, NONEHighlighting
const highlighted = await index.query({
filter: { name: { $eq: "laptop" } },
select: { name: true },
highlight: {
fields: ["name"],
preTag: "<mark>", // optional, default <em>
postTag: "</mark>", // optional, default </em>
},
});
// data.name: "Gaming <mark>Laptop</mark>"Filter Operators
Text Field Filters
// Exact substring match
{ name: { $eq: "laptop" } }
// Multiple values (OR)
{ name: { $in: ["laptop", "tablet"] } }
// Fuzzy matching (typo tolerance)
{ name: { $fuzzy: { term: "lapto", distance: 1 } } }
// Phrase matching (adjacent words with tolerance)
{ name: { $phrase: { text: "gaming laptop", slop: 1 } } }
// Regex pattern
{ name: { $regex: "lap.*" } }
// Smart matching (automatic fuzzy + phrase + term)
{ name: { $smart: "gaming laptop" } }Numeric Field Filters
// Exact value
{ price: { $eq: 29.99 } }
// Range
{ price: { $gte: 10, $lte: 100 } }
// Greater/less than
{ price: { $gt: 50 } }
{ stock: { $lt: 10 } }Boolean Field Filters
{
inStock: {
$eq: true;
}
}
{
inStock: {
$in: [true, false];
}
}Date Field Filters
{ createdAt: { $gte: "2024-01-01", $lt: "2025-01-01" } }Keyword Field Filters
// Exact match
{ category: { $eq: "electronics" } }
// Multiple values
{ category: { $in: ["electronics", "accessories"] } }
// Lexicographic range
{ category: { $gte: "a", $lt: "m" } }Facet Field Filters
{
brand: {
$eq: "Apple";
}
}
{
brand: {
$in: ["Apple", "Samsung"];
}
}Boolean Operators
Combine filters using boolean operators:
// AND - all conditions must match
{
$and: [
{ category: { $eq: "electronics" } },
{ price: { $lte: 500 } },
]
}
// OR - any condition matches
{
$or: [
{ category: { $eq: "electronics" } },
{ category: { $eq: "accessories" } },
]
}
// MUST + MUST NOT - require some, exclude others
{
$must: [{ category: { $eq: "electronics" } }],
$mustNot: [{ inStock: { $eq: false } }],
}
// MUST + SHOULD - required conditions + optional boosters
{
$must: [{ category: { $eq: "electronics" } }],
$should: [{ name: { $eq: "premium" } }], // boosts score if matched
}
// SHOULD alone - at least one must match (acts like OR)
{
$should: [
{ name: { $eq: "laptop" } },
{ name: { $eq: "tablet" } },
]
}Boosting
Boost the score of specific conditions:
{
$must: [
{ name: { $eq: "laptop", $boost: 2.0 } }, // double the score weight
{ category: { $eq: "electronics", $boost: 0.5 } },
];
}Counting
Count matching documents without returning them:
const { count } = await index.count({
filter: { category: { $eq: "electronics" } },
});
// count: 2@upstash/redis is an HTTP/REST based Redis client for typescript, built on top of Upstash REST API. This project is in GA Stage. The Upstash Professional Support fully covers this project. It receives regular updates, and bug fixes.
Repo: upstash/redis-js
Other commands on redis-js.
- /aggregating
Run analytics over indexed data using metric and bucket aggregations. Compute statistics, group documents, build histograms, and perform faceted navigation. Aggregations can be nested for multi-level analysis.
Open command - /aliases
Index aliases provide an indirection layer between your application and the actual index. You can point an alias to any index and swap it atomically, enabling zero-downtime reindexing.
Open command - /index-management
Create, inspect, and drop search indexes. Wait for indexing to complete after data changes. Indexes automatically track Redis keys matching a specified prefix.
Open command

