Filtres, tri & pagination
Référence complète pour les expressions de filtre, les options de tri, les facettes et la pagination dans les requêtes AACsearch.
AACsearch utilise la syntaxe de filtre et de tri de AACSearch avec quelques conventions spécifiques au schéma produit. Cette page est une référence complète pour la construction d'expressions de filtre, la configuration des ordres de tri et la pagination des résultats.
Syntaxe des expressions de filtre
Les filtres sont spécifiés comme une chaîne de caractères utilisant la logique booléenne.
Égalité
availability:=in_stock
brand:=Sony
categories:=Electronics
locale:=enNégation
availability:!=out_of_stock
brand:!=CompetitorsPlage (numérique)
price:>50
price:<200
price:[50..200] # plage inclusive
price:(50..200) # plage exclusiveAppartenance à un tableau
categories:=[Electronics, Audio]
brand:=[Sony, Bose, Sennheiser]Contient une chaîne / préfixe
AACSearch ne supporte que la correspondance exacte de chaîne pour les champs de facette. Pour la recherche par préfixe, utilisez q avec queryBy.
Logique booléenne
# ET (les deux conditions doivent correspondre)
availability:=in_stock && price:<200
# OU (l'une ou l'autre condition correspond)
brand:=Sony || brand:=Bose
# Regroupement
(brand:=Sony || brand:=Bose) && availability:=in_stock && price:<200Filtre de locataire (automatique)
Le handler public ajoute automatiquement :
organization_id:={organizationId}Vous n'avez pas besoin d'ajouter ce filtre manuellement — il est toujours appliqué.
Champs de filtre disponibles
Le schéma produit par défaut inclut ces champs filtrables (marqués facet: true) :
| Champ | Type | Exemple de filtre |
|---|---|---|
brand | string | brand:=Sony |
categories | string[] | categories:=[Electronics, Audio] |
availability | string | availability:=in_stock |
price | float | price:[10..500] |
sale_price | float | sale_price:<100 |
locale | string | locale:=en |
Facettes
Les facettes calculent la distribution des valeurs pour un champ sur les documents correspondants. Utilisez-les pour afficher les barres latérales de filtres.
{
"q": "headphones",
"facetBy": "brand,categories,availability"
}La réponse inclut 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 }
]
}
]
}Facettes avec filtres appliqués
Lorsqu'un filtre est actif, les comptages de facettes reflètent l'ensemble de résultats filtré, pas l'index entier :
{
"q": "*",
"filterBy": "brand:=Sony",
"facetBy": "categories,availability"
}Cela retourne les comptages de catégories et de disponibilité pour les produits Sony uniquement.
Tri
Tri sur un seul champ
{ "sortBy": "price:asc" }
{ "sortBy": "price:desc" }
{ "sortBy": "created_at:desc" }
{ "sortBy": "sale_price:asc" }Tri par pertinence d'abord (par défaut)
{ "sortBy": "_text_match:desc" }C'est le comportement par défaut lorsque sortBy est omis.
Tri multi-champ (départage)
{ "sortBy": "_text_match:desc,price:asc" }Trie par score de pertinence d'abord ; à score égal, trie par prix croissant.
Préréglages de tri courants
| Libellé | Valeur sortBy |
|---|---|
| Le plus pertinent | _text_match:desc |
| Prix : du moins cher | price:asc |
| Prix : du plus cher | price:desc |
| Les plus récents | created_at:desc |
| Prix promotionnel : du moins cher | sale_price:asc |
Pagination
{
"page": 1, // indexé à partir de 1, défaut : 1
"perPage": 20 // défaut : 10, max : 100
}Champs de réponse pour la pagination :
{
"found": 142, // total de documents correspondants
"page": 1, // page actuelle
"outOf": 5000 // total de documents dans l'index (non filtré)
}Calcul du nombre total de pages :
const totalPages = Math.ceil(results.found / perPage);
const hasMore = results.page * perPage < results.found;Avertissement sur la pagination profonde
Les performances de AACSearch se dégradent avec de grandes valeurs de page pour les indexes de plus de 100 000 documents.
Pour la pagination profonde ou les exports :
- Utilisez des valeurs de
pagecroissantes avec unperPagefixe - Ou implémentez une pagination basée sur curseur en triant sur un champ unique (
id:asc) et en utilisantfilterBy: "id:>lastSeenId"
Sélection de champs
Réduisez la taille de la réponse en sélectionnant uniquement les champs dont vous avez besoin :
{
"includeFields": "id,title,price,brand,availability",
"excludeFields": "description,tags"
}Utilisez excludeFields pour supprimer les grands champs de texte des réponses lorsque vous ne les affichez pas
(par ex. description dans une autocomplétion de recherche au fil de la frappe qui n'affiche que les titres).
Combiner les filtres avec les tokens limités
Lorsqu'un token limité est utilisé, son scopedFilter est combiné avec ET avec le filterBy de l'appelant :
Token scopedFilter : "price:<100"
Appelant filterBy : "brand:=Sony && availability:=in_stock"
filterBy effectif : "brand:=Sony && availability:=in_stock && price:<100"Le filtre du token ne peut pas être remplacé par le filterBy de l'appelant.
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
}Multi-search & Requêtes
Exécuter plusieurs requêtes de recherche en une seule requête pour l'autocomplétion, la recherche fédérée et les scénarios multi-index.
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.