Filter, Sortierung & Seitenumbruch
Vollständige Referenz für Filterausdrücke, Sortieroptionen, Facettierung und Seitenumbruch in AACsearch-Abfragen.
AACsearch verwendet die Filter- und Sortiersyntax von AACSearch mit einigen produktschema-spezifischen Konventionen. Diese Seite ist eine vollständige Referenz für das Erstellen von Filterausdrücken, das Konfigurieren von Sortierreihenfolgen und das Paginieren von Ergebnissen.
Filterausdruck-Syntax
Filter werden als Zeichenkette mit boolescher Logik angegeben.
Gleichheit
availability:=in_stock
brand:=Sony
categories:=Electronics
locale:=deNegation
availability:!=out_of_stock
brand:!=CompetitorsBereich (numerisch)
price:>50
price:<200
price:[50..200] # inklusiver Bereich
price:(50..200) # exklusiver BereichArray-Mitgliedschaft
categories:=[Electronics, Audio]
brand:=[Sony, Bose, Sennheiser]Zeichenkette enthält / Präfix
AACSearch unterstützt nur exakten Zeichenkettenabgleich für Facettenfelder. Für Präfix-Suche verwenden Sie q mit queryBy.
Boolesche Logik
# UND (beide Bedingungen müssen übereinstimmen)
availability:=in_stock && price:<200
# ODER (eine der Bedingungen stimmt überein)
brand:=Sony || brand:=Bose
# Gruppierung
(brand:=Sony || brand:=Bose) && availability:=in_stock && price:<200Mandantenfilter (automatisch)
Der öffentliche Handler hängt automatisch folgendes voran:
organization_id:={organizationId}Sie müssen diesen Filter nicht manuell hinzufügen — er wird immer angewendet.
Verfügbare Filterfelder
Das Standard-Produktschema enthält diese filterbaren Felder (als facet: true markiert):
| Feld | Typ | Beispielfilter |
|---|---|---|
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:=de |
Facettierung
Facetten berechnen die Werteverteilung für ein Feld über übereinstimmende Dokumente. Verwenden Sie sie zum Rendern von Filter-Seitenleisten.
{
"q": "headphones",
"facetBy": "brand,categories,availability"
}Antwort enthält 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 }
]
}
]
}Facetten mit angewendeten Filtern
Wenn ein Filter aktiv ist, spiegeln Facettenzählungen die gefilterte Ergebnismenge wider, nicht den gesamten Index:
{
"q": "*",
"filterBy": "brand:=Sony",
"facetBy": "categories,availability"
}Dies gibt Kategorien und Verfügbarkeitszählungen nur für Sony-Produkte zurück.
Sortierung
Einzelfeld-Sortierung
{ "sortBy": "price:asc" }
{ "sortBy": "price:desc" }
{ "sortBy": "created_at:desc" }
{ "sortBy": "sale_price:asc" }Relevanz-zuerst-Sortierung (Standard)
{ "sortBy": "_text_match:desc" }Dies ist der Standard, wenn sortBy weggelassen wird.
Mehrfeld-Sortierung (Gleichstand-Auflösung)
{ "sortBy": "_text_match:desc,price:asc" }Sortiert zuerst nach Relevanzbewertung; innerhalb derselben Bewertung nach Preis aufsteigend.
Häufige Sortier-Presets
| Bezeichnung | sortBy-Wert |
|---|---|
| Relevanteste | _text_match:desc |
| Preis: günstigste zuerst | price:asc |
| Preis: teuerste zuerst | price:desc |
| Neueste zuerst | created_at:desc |
| Angebotspreis: günstigste zuerst | sale_price:asc |
Seitenumbruch
{
"page": 1, // 1-indiziert, Standard: 1
"perPage": 20 // Standard: 10, Max: 100
}Antwortfelder für den Seitenumbruch:
{
"found": 142, // Gesamtzahl übereinstimmender Dokumente
"page": 1, // Aktuelle Seite
"outOf": 5000 // Gesamtdokumente im Index (ungefiltert)
}Gesamtseiten berechnen:
const totalPages = Math.ceil(results.found / perPage);
const hasMore = results.page * perPage < results.found;Warnung bei tiefer Paginierung
Die Leistung verschlechtert sich bei großen page-Werten für Indizes über 100.000 Dokumente.
Für tiefe Paginierung oder Exporte:
- Steigende
page-Werte mit festemperPageverwenden - Oder cursorbasierte Paginierung implementieren, indem ein eindeutiges Feld sortiert wird (
id:asc) undfilterBy: "id:>lastSeenId"verwendet wird
Feldauswahl
Reduzieren Sie die Antwortgröße, indem Sie nur die Felder auswählen, die Sie benötigen:
{
"includeFields": "id,title,price,brand,availability",
"excludeFields": "description,tags"
}Verwenden Sie excludeFields, um große Textfelder aus Antworten zu entfernen, wenn Sie sie nicht rendern
(z. B. description in einer Suche-während-der-Eingabe-Autocomplete, die nur Titel anzeigt).
Filter mit eingeschränkten Token kombinieren
Wenn ein eingeschränktes Token verwendet wird, wird sein scopedFilter UND-verknüpft mit dem filterBy des Aufrufers:
Token-scopedFilter: "price:<100"
Aufrufer-filterBy: "brand:=Sony && availability:=in_stock"
Effektiver filterBy: "brand:=Sony && availability:=in_stock && price:<100"Der Filter des Tokens kann nicht vom filterBy des Aufrufers überschrieben werden.
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-Suche & Abfragen
Mehrere Suchanfragen in einer einzigen Anfrage für Autocomplete, föderierte Suche und Multi-Index-Szenarien ausführen.
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.