GeoLeaf Search Engine — Guide de configuration et benchmark
Module : @geoleaf/core — lazy chunk search
Version : 2.0.0
Moteur par défaut : native (fallback includes(), zéro dépendance)
Dernière mise à jour : mars 2026
Sommaire
- Vue d'ensemble
- Activation de FlexSearch
- Configuration du profil
- API publique GeoLeaf.Search
- Champs indexés
- Gestion incrémentale
- Benchmark
- Sécurité
- Migration depuis la recherche native
Vue d'ensemble
GeoLeaf propose deux moteurs de recherche full-text activables via le profil JSON :
| Moteur | Config | Avantages | Inconvénients |
|---|---|---|---|
native | (défaut, aucune config) | Zéro dépendance, ~0 KB supplémentaire | O(n) par requête, pas de normalisation des accents avancée |
flexsearch | search.engine: "flexsearch" | Sub-milliseconde (O(1)), prefix match, normalisation diacritiques, indexation incrémentale | Chunk JS supplémentaire ~6 KB gzip (lazy-loadé) |
Le moteur flexsearch est lazy-loadé : aucun impact sur le bundle initial si non activé.
Activation de FlexSearch
Via le profil JSON
{
"search": {
"engine": "flexsearch"
}
}Via chargement dynamique (ESM)
// Force le chargement du module search (normalement déclenché par GeoLeaf._loadModule)
await GeoLeaf._loadModule("search");Configuration du profil
Champs indexés personnalisés
Par défaut, les champs title, label, name sont indexés. Pour personnaliser, utilisez la propriété search: true dans panels.detail.layout :
{
"panels": {
"detail": {
"layout": [
{ "field": "title", "search": true },
{ "field": "attributes.commune", "search": true },
{ "field": "attributes.tags", "search": true }
]
}
}
}Ou via panels.search.filters :
{
"panels": {
"search": {
"filters": [
{
"type": "search",
"searchFields": ["title", "attributes.commune", "attributes.description"]
}
]
}
}
}Chemins imbriqués : utilisez la notation pointée (ex.
attributes.commune). Tableaux : les valeurs de type array sont automatiquement concaténées.
API publique GeoLeaf.Search
Disponible après chargement du module search (lazy ou via _loadModule("search")).
GeoLeaf.Search.isReady()
GeoLeaf.Search.isReady(): booleanRetourne true quand l'index est construit et prêt à répondre aux requêtes.
GeoLeaf.Search.query(text)
GeoLeaf.Search.query(text: string): Set<string>Retourne un Set d'identifiants POI correspondant à la recherche. Retourne un Set vide si le moteur n'est pas prêt (fallback automatique dans les filtres).
GeoLeaf.Search.build(pois)
GeoLeaf.Search.build(pois: object[]): voidReconstruit l'index à partir d'un tableau de POI. Utile après un changement de profil.
GeoLeaf.Search.getEngine()
GeoLeaf.Search.getEngine(): string // "flexsearch" | "native"Retourne le nom du moteur actif : "flexsearch" si l'index FlexSearch est prêt, "native" sinon (fallback includes()).
GeoLeaf.Search.clear()
GeoLeaf.Search.clear(): voidVide l'index. Les requêtes suivantes retournent un Set vide jusqu'au prochain build().
Exemple d'utilisation
// After loading the search module
await GeoLeaf._loadModule("search");
if (GeoLeaf.Search.isReady()) {
const results = GeoLeaf.Search.query("abbaye");
console.log("Matching POI IDs:", [...results]);
}Champs indexés
L'index est construit en concaténant le texte de tous les champs indexés par POI :
poi.title + " " + poi.attributes.commune + " " + poi.attributes.tags[0] + ...Le moteur FlexSearch utilise :
tokenize: "forward"— correspondance préfixe ("rando" → "randonnée")encoder: "advanced"— normalisation complète des diacritiques ("eglise" → "Église")
Gestion incrémentale
Le registry écoute automatiquement les événements DOM GeoLeaf pour maintenir l'index à jour :
| Événement | Action |
|---|---|
geoleaf:poi:loaded | Reconstruit l'index complet |
geoleaf:poi:added | Ajoute le nouveau POI (O(1)) |
geoleaf:poi:removed | Supprime le POI (O(1)) |
Avec FlexSearchEngine, les opérations add/remove sont vraiment incrémentales — pas de rebuild complet.
Benchmark
Mesures effectuées sur Chrome 121, machine de développement (Ryzen 7, 16 GB RAM).
Temps de construction index (build())
| Volume | Native (ms) | FlexSearch (ms) |
|---|---|---|
| 500 POI | — (pas d'index) | ~8 ms |
| 1 000 POI | — | ~15 ms |
| 5 000 POI | — | ~70 ms |
| 10 000 POI | — | ~140 ms |
Temps de requête (query())
| Volume | Native includes() (ms/requête) | FlexSearch (ms/requête) |
|---|---|---|
| 500 POI | ~0.3 | ~0.05 |
| 1 000 POI | ~0.6 | ~0.05 |
| 5 000 POI | ~3.1 | ~0.05 |
| 10 000 POI | ~6.5 | ~0.05 |
Conclusion : FlexSearch devient significativement plus rapide dès ~1 000 POI. En dessous de 500 POI, le fallback natif est suffisant.
Taille de l'index en mémoire (approximatif)
| Volume | FlexSearch (MB) |
|---|---|
| 1 000 POI | ~0.8 MB |
| 5 000 POI | ~3.5 MB |
| 10 000 POI | ~7.0 MB |
Sécurité
- Sanitisation des requêtes :
_sanitizeQueryInput()supprime les caractères de contrôle (\x00–\x1F,\x7F) et tronque à 200 caractères. Aucun risque XSS car le résultat est unSetd'ID (chaînes de caractères), jamais injecté dans le DOM. - Protection prototype : les chemins de champs (
__proto__,constructor,prototype) sont ignorés pendant la construction du texte indexé. - Données POI : sanitisées à l'ingestion via
Security.sanitizePoiProperties()avant d'être indexées. - IDs : normalisés en
String()pour éviter toute injection par coercition de type.
Migration depuis la recherche native
La migration est transparente et non-breaking :
- Ajouter
"search": { "engine": "flexsearch" }au profil JSON. - GeoLeaf charge automatiquement le chunk
searchau démarrage. - L'index est construit sur l'événement
geoleaf:poi:loaded. - Si le moteur n'est pas encore prêt (ex. premier rendu), le filtre retombe automatiquement sur
includes().
Aucune modification du code applicatif n'est requise.
Version : 2.0.0
Dernière mise à jour : mars 2026
