Filtros, Ordenación y Paginación
Referencia completa para expresiones de filtro, opciones de ordenación, facetado y paginación en las consultas de AACsearch.
AACsearch usa la sintaxis de filtro y ordenación de AACSearch con algunas convenciones específicas del esquema de productos. Esta página es una referencia completa para construir expresiones de filtro, configurar órdenes de clasificación y paginar resultados.
Sintaxis de expresión de filtro
Los filtros se especifican como una cadena usando lógica booleana.
Igualdad
availability:=in_stock
brand:=Sony
categories:=Electrónica
locale:=esNegación
availability:!=out_of_stock
brand:!=CompetidoresRango (numérico)
price:>50
price:<200
price:[50..200] # rango inclusivo
price:(50..200) # rango exclusivoPertenencia a array
categories:=[Electrónica, Audio]
brand:=[Sony, Bose, Sennheiser]Contiene cadena / prefijo
AACSearch admite solo coincidencia exacta de cadena para campos con faceta. Para búsqueda de prefijo, use q con queryBy.
Lógica booleana
# AND (ambas condiciones deben coincidir)
availability:=in_stock && price:<200
# OR (cualquier condición coincide)
brand:=Sony || brand:=Bose
# Agrupación
(brand:=Sony || brand:=Bose) && availability:=in_stock && price:<200Filtro de tenant (automático)
El manejador público antepone automáticamente:
organization_id:={organizationId}No necesita añadir este filtro manualmente — siempre se aplica.
Campos de filtro disponibles
El esquema de producto predeterminado incluye estos campos filtrables (marcados como facet: true):
| Campo | Tipo | Ejemplo de filtro |
|---|---|---|
brand | string | brand:=Sony |
categories | string[] | categories:=[Electrónica, Audio] |
availability | string | availability:=in_stock |
price | float | price:[10..500] |
sale_price | float | sale_price:<100 |
locale | string | locale:=es |
Facetado
Las facetas calculan la distribución de valores para un campo entre los documentos coincidentes. Úselas para renderizar barras laterales de filtros.
{
"q": "auriculares",
"facetBy": "brand,categories,availability"
}La respuesta incluye facetCounts:
{
"facetCounts": [
{
"fieldName": "brand",
"counts": [
{ "value": "Sony", "count": 45 },
{ "value": "Bose", "count": 28 },
{ "value": "Sennheiser", "count": 19 }
]
},
{
"fieldName": "availability",
"counts": [
{ "value": "in_stock", "count": 89 },
{ "value": "out_of_stock", "count": 23 }
]
}
]
}Facetas con filtros aplicados
Cuando un filtro está activo, los recuentos de facetas reflejan el conjunto de resultados filtrado, no todo el índice:
{
"q": "*",
"filterBy": "brand:=Sony",
"facetBy": "categories,availability"
}Esto devuelve recuentos de categorías y disponibilidad solo para los productos de Sony.
Ordenación
Ordenación por un solo campo
{ "sortBy": "price:asc" }
{ "sortBy": "price:desc" }
{ "sortBy": "created_at:desc" }
{ "sortBy": "sale_price:asc" }Ordenación por relevancia primero (predeterminado)
{ "sortBy": "_text_match:desc" }Este es el predeterminado cuando se omite sortBy.
Ordenación por múltiples campos (desempate)
{ "sortBy": "_text_match:desc,price:asc" }Ordena primero por puntuación de relevancia; dentro de la misma puntuación, ordena por precio ascendente.
Presets de ordenación comunes
| Etiqueta | Valor de sortBy |
|---|---|
| Más relevante | _text_match:desc |
| Precio: menor a mayor | price:asc |
| Precio: mayor a menor | price:desc |
| Más recientes primero | created_at:desc |
| Precio de oferta: menor a mayor | sale_price:asc |
Paginación
{
"page": 1, // indexado desde 1, predeterminado: 1
"perPage": 20 // predeterminado: 10, máx.: 100
}Campos de respuesta para paginación:
{
"found": 142, // total de documentos coincidentes
"page": 1, // página actual
"outOf": 5000 // total de documentos en el índice (sin filtrar)
}Calcular el total de páginas:
const totalPages = Math.ceil(results.found / perPage);
const hasMore = results.page * perPage < results.found;Advertencia de paginación profunda
El rendimiento de AACSearch se degrada con valores grandes de page para índices con más de 100K documentos.
Para paginación profunda o exportaciones:
- Use valores crecientes de
pagecon unperPagefijo - O implemente paginación basada en cursor ordenando por un campo único (
id:asc) y usandofilterBy: "id:>lastSeenId"
Selección de campos
Reduzca el tamaño de la respuesta seleccionando solo los campos que necesita:
{
"includeFields": "id,title,price,brand,availability",
"excludeFields": "description,tags"
}Use excludeFields para eliminar campos de texto grandes de las respuestas cuando no los renderiza
(por ejemplo, description en un autocompletado de búsqueda mientras se escribe que solo muestra títulos).
Combinar filtros con tokens con ámbito
Cuando se usa un token con ámbito, su scopedFilter se combina con AND con el filterBy del llamador:
scopedFilter del token: "price:<100"
filterBy del llamador: "brand:=Sony && availability:=in_stock"
filterBy efectivo: "brand:=Sony && availability:=in_stock && price:<100"El filtro del token no puede ser anulado por el filterBy del llamador.
Escaping values
Filter values are parsed by AACSearch's filter expression engine. Most strings work as-is, but a few characters have special meaning and must be backtick-quoted (or backslash-escaped) when they appear inside a value:
| Character | Meaning in the grammar | Inside a value, write as |
|---|---|---|
, | Array element separator | Wrap value in `…` |
&& | AND operator | Wrap value in `…` |
|| | OR operator | Wrap value in `…` |
( ) | Grouping | Wrap value in `…` |
[ ] | Range / array delimiters | Wrap value in `…` |
: | Field/operator separator | Wrap value in `…` |
` | The quote character itself | Escape with backslash: \` |
Examples:
# Brand name contains a comma — must be quoted
brand:=`Ben & Jerry's`
# Category contains the AND operator literally
categories:=`Home && Garden`User-controlled values must always be escaped before concatenation. Never interpolate user input into the filter string directly — use the safe filter builder.
Safe filter builder
Hand-concatenating a filter string from user input is a category-1 injection bug. Always build filters from a structured representation. A minimal TypeScript builder:
type AtomicFilter =
| { field: string; op: "="; value: string | number | boolean }
| { field: string; op: "!="; value: string | number | boolean }
| { field: string; op: ">" | "<" | ">=" | "<="; value: number }
| { field: string; op: "in"; values: Array<string | number> }
| { field: string; op: "range"; min: number; max: number; inclusive?: boolean };
type FilterTree = AtomicFilter | { and: FilterTree[] } | { or: FilterTree[] };
const FIELD_RE = /^[a-z_][a-z0-9_]*$/;
function escapeValue(v: string | number | boolean): string {
if (typeof v === "number" || typeof v === "boolean") return String(v);
return "`" + String(v).replace(/`/g, "\\`") + "`";
}
function fieldOrThrow(field: string): string {
if (!FIELD_RE.test(field)) throw new Error(`invalid field name: ${field}`);
return field;
}
export function buildFilter(node: FilterTree): string {
if ("and" in node) return node.and.map(buildFilter).join(" && ");
if ("or" in node) return "(" + node.or.map(buildFilter).join(" || ") + ")";
const f = fieldOrThrow(node.field);
if (node.op === "in") return `${f}:=[${node.values.map(escapeValue).join(", ")}]`;
if (node.op === "range") {
const [lo, hi] = node.inclusive === false ? ["(", ")"] : ["[", "]"];
return `${f}:${lo}${node.min}..${node.max}${hi}`;
}
return `${f}:${node.op}${escapeValue(node.value)}`;
}The builder enforces two invariants: field names match a strict identifier regex, and every string value is backtick-quoted with inner backticks escaped. Replicate the same shape in your server SDK.
E-commerce filter recipes
Category page (in-stock only)
{
"filterBy": "categories:=`Audio` && availability:=in_stock",
"facetBy": "brand,price",
"sortBy": "_text_match:desc,popularity_score:desc"
}Multi-brand drill-down
filterBy: "categories:=[`Electronics`, `Audio`] && brand:=[`Sony`, `Bose`] && availability:=in_stock"Price range with "on sale" branch
filterBy: "categories:=`Audio` && availability:=in_stock && (sale_price:[10..100] || (sale_price:<0 && price:[10..100]))"Locale-aware listing
filterBy: "locale:=`en` && categories:=`Audio` && availability:=in_stock""More like this" (vector hybrid)
{
"q": "*",
"vectorQuery": "embedding:([…current vector…], k:50)",
"filterBy": "id:!=`product-123` && availability:=in_stock && price:[1000..15000]",
"perPage": 12
}Búsqueda Múltiple y Consultas
Ejecute múltiples consultas de búsqueda en una sola solicitud para autocompletado, búsqueda federada y escenarios de múltiples índices.
Search Core Relevance
Query processing, queryBy weights, typo tolerance, synonyms, curations, ranking — the developer-side reference for how the search engine decides which documents to return.