Bleve en pratique : Construire une solution de recherche d'entreprise

Bleve en pratique : Construire une solution de recherche d'entreprise

Cet article explore en profondeur comment utiliser Bleve pour construire une solution de recherche complète de niveau entreprise. Nous couvrons l'utilisation détaillée des outils CLI Bleve et l'écriture de scripts automatisés, les meilleures pratiques pour l'indexation par lots de données à grande échelle, les stratégies de déploiement en environnement distribué, ainsi qu'un guide complet de surveillance, d'optimisation et de dépannage. À travers des exemples de code concrets et des conceptions architecturales, nous démontrons comment implémenter un système de recherche haute performance et haute disponibilité.

Utilisation des outils CLI Bleve et automatisation

Bleve offre une interface de ligne de commande (CLI) puissante permettant aux développeurs d'interagir avec les index sans écrire de code. Cet outil, construit sur le framework Cobra, fournit des fonctionnalités complètes de gestion d'index, de manipulation de données et d'interrogation, ce qui en fait un outil indispensable pour le développement et les opérations.

Installation et utilisation de base de la CLI

L'installation de l'outil CLI Bleve s'effectue comme suit :

go install github.com/blevesearch/bleve/v2/cmd/bleve@latest

Une fois l'installation terminée, vous pouvez consulter toutes les commandes disponibles avec bleve --help :

$ bleve --help
Bleve est un outil en ligne de commande pour interagir avec un index Bleve.

Usage:
  bleve [command]

Available Commands:
  bulk        charge en masse depuis des fichiers JSON délimités par des nouvelles lignes
  check       vérifie le contenu de l'index
  count       compte le nombre de documents dans l'index
  create      crée un nouvel index
  dictionary  affiche le dictionnaire de termes pour le champ spécifié dans l'index
  dump        affiche le contenu de l'index
  fields      liste les champs de cet index
  help        Aide sur une commande
  index       ajoute les fichiers à l'index
  mapping     affiche le mappage utilisé pour cet index
  query       interroge l'index
  registry    liste les composants Bleve compilés dans cet exécutable
  scorch      outil en ligne de commande pour interagir avec un index scorch

Description détaillée des commandes principales

Création et gestion des index

La création d'un nouvel index est la première étape avec Bleve, et la commande create prend en charge diverses options de configuration :

# Créer un index de base
bleve create monindex.bleve

# Créer un index avec une configuration de mappage personnalisée
bleve create --mapping mappage.json monindex.bleve

# Spécifier le type de stockage et le type d'index
bleve create --store boltdb --index scorch monindex.bleve

Importation de données et traitement par lots

La CLI Bleve propose deux méthodes d'importation de données : l'indexation de fichiers uniques et le traitement par lots.

Indexation de fichiers uniques :

# Indexer un seul fichier JSON
bleve index monindex.bleve donnees.json

# Indexer tous les fichiers d'un répertoire
bleve index monindex.bleve donnees/

# Conserver les noms de fichiers et extensions originaux
bleve index --keepDir --keepExt monindex.bleve donnees/

Traitement par lots (recommandé pour les grands ensembles de données) :

# Importer en masse un fichier NDJSON
bleve bulk --batch 5000 monindex.bleve donnees.ndjson

# Importer en masse plusieurs fichiers
bleve bulk monindex.bleve donnees1.ndjson donnees2.ndjson

# Personnaliser la taille du lot
bleve bulk --batch 10000 monindex.bleve donnees_volumineuses.ndjson

Opérations de recherche et d'interrogation

Les fonctionnalités de requête prennent en charge plusieurs types de requêtes et de nombreuses options :

# Recherche par chaîne de base
bleve query monindex.bleve "terme de recherche"

# Spécifier le type de requête
bleve query --type term monindex.bleve "terme_exact"
bleve query --type prefix monindex.bleve "prefixe_"

# Requête avec limitation de champ
bleve query --field titre monindex.bleve "titre spécifique"

# Options de requête avancées
bleve query --limit 20 --skip 10 --explain --highlight monindex.bleve "requete"

# Trier les résultats
bleve query --sort-by "-score,date" monindex.bleve "requete"

Maintenance et diagnostic de l'index
# Statistiques sur le nombre de documents
bleve count monindex.bleve

# Lister tous les champs
bleve fields monindex.bleve

# Voir la configuration de mappage de l'index
bleve mapping monindex.bleve

# Vérifier l'intégrité de l'index
bleve check monindex.bleve

# Voir le dictionnaire des champs
bleve dictionary monindex.bleve nom_du_champ

Scripts d'automatisation et intégration

Les outils CLI Bleve sont parfaitement adaptés aux processus automatisés. Voici quelques scénarios d'automatisation courants :

Script de construction d'index par lots
#!/bin/bash
# construire_index.sh

NOM_INDEX="monindexderecherche.bleve"
REPERTOIRE_DONNEES="./donnees"
FICHIER_MAPPAGE="./mappage.json"

# Nettoyer l'ancien index
rm -rf $NOM_INDEX

# Créer le nouvel index
bleve create --mapping $FICHIER_MAPPAGE $NOM_INDEX

# Importer les données en masse
for fichier in $REPERTOIRE_DONNEES/*.ndjson; do
    echo "Traitement de $fichier..."
    bleve bulk --batch 5000 $NOM_INDEX "$fichier"
done

# Vérifier l'index
echo "Statistiques de l'index :"
bleve count $NOM_INDEX
blege fields $NOM_INDEX

Script de mise à jour périodique des données
#!/bin/bash
# mettre_a_jour_index.sh

NOM_INDEX="monindexderecherche.bleve"
REPERTOIRE_MISES_A_JOUR="./misesajour"

# Traiter les fichiers de mise à jour incrémentale
for fichier_maj in $REPERTOIRE_MISES_A_JOUR/miseajour_*.ndjson; do
    if [ -f "$fichier_maj" ]; then
        echo "Application de la mise à jour : $fichier_maj"
        bleve bulk $NOM_INDEX "$fichier_maj"
        # Déplacer les fichiers traités
        mv "$fichier_maj" "$REPERTOIRE_MISES_A_JOUR/traites/"
    fi
done

Script de surveillance et de vérification de santé
#!/bin/bash
# verification_sante.sh

NOM_INDEX="monindexderecherche.bleve"
FICHIER_JOURNAL="./sante.log"

{
    echo "=== Vérification de santé $(date) ==="
    echo "Nombre de documents : $(bleve count $NOM_INDEX)"
    echo "Vérification de l'index : $(bleve check $NOM_INDEX 2>&1)"
    echo "Champs : $(bleve fields $NOM_INDEX)"
} >> $FICHIER_JOURNAL

Modèles d'automatisation avancés

Utilisation de Makefile pour gérer le cycle de vie des index
.PHONY: index clean query stats

INDEX := monindex.bleve
DONNEES := donnees/*.ndjson

index: clean
	bleve create $(INDEX)
	bleve bulk --batch 5000 $(INDEX) $(DONNEES)

clean:
	rm -rf $(INDEX)

query:
	bleve query $(INDEX) "$(q)"

stats:
	bleve count $(INDEX)
	bleve fields $(INDEX)

Intégration au pipeline CI/CD
# .github/workflows/index-recherche.yml
name: Construction de l'index de recherche

on:
  push:
    branches: [ main ]
  schedule:
    - cron: '0 2 * * *'  # Exécution quotidienne à 2h du matin

jobs:
  construire-index:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    
    - name: Configurer Go
      uses: actions/setup-go@v3
      with:
        go-version: '1.19'
    
    - name: Installer la CLI Bleve
      run: go install github.com/blevesearch/bleve/v2/cmd/bleve@latest
    
    - name: Construire l'index de recherche
      run: |
        bleve create index_recherche.bleve
        bleve bulk index_recherche.bleve donnees/*.ndjson
        bleve count index_recherche.bleve
    
    - name: Téléverser l'artefact de l'index
      uses: actions/upload-artifact@v3
      with:
        name: index-recherche
        path: index_recherche.bleve

Optimisation des performances et meilleures pratiques

Optimisation du traitement par lots
# Ajuster la taille du lot selon la mémoire système
MEMOIRE_GO=$(free -g | awk '/Mem:/ {print $2}')
TAILLE_LOT=$((MEMOIRE_GO * 500))

bleve bulk --batch $TAILLE_LOT monindex.bleve donnees.ndjson

Script de traitement parallèle
#!/bin/bash
# indexation_parallele.sh

NOM_INDEX="monindex.bleve"
FICHIERS_DONNEES=("donnees1.ndjson" "donnees2.ndjson" "donnees3.ndjson")

# Traiter plusieurs fichiers en parallèle
for fichier in "${FICHIERS_DONNEES[@]}"; do
    (bleve bulk $NOM_INDEX "$fichier") &
done

# Attendre que toutes les tâches d'arrière-plan soient terminées
wait

echo "Tous les fichiers traités"

Gestion des erreurs et journalisation

Dans un environnement de production, un mécanisme robuste de gestion des erreurs est essentiel :

#!/bin/bash
# indexation_securisee.sh

NOM_INDEX="monindex.bleve"
FICHIER_JOURNAL="./journal_indexation.log"

indexer_fichier() {
    local fichier=$1
    echo "$(date): Début de l'indexation de $fichier" >> $FICHIER_JOURNAL
    if bleve bulk $NOM_INDEX "$fichier" 2>> $FICHIER_JOURNAL; then
        echo "$(date): Succès de l'indexation de $fichier" >> $FICHIER_JOURNAL
        return 0
    else
        echo "$(date): Échec de l'indexation de $fichier" >> $FICHIER_JOURNAL
        return 1
    fi
}

# Traiter tous les fichiers de données
for fichier in donnees/*.ndjson; do
    if ! indexer_fichier "$fichier"; then
        echo "Erreur critique : Échec de l'indexation de $fichier" >&2
        exit 1
    fi
done

En exploitant judicieusement ces caractéristiques et ces modèles d'automatisation de la CLI Bleve, vous pouvez construire un système de gestion d'index de recherche efficace et fiable, améliorant considérablement l'efficacité du développement et des opérations.

Meilleures pratiques pour l'indexation par lots de données à grande échelle

Dans les scénarios d'indexation de données à grande échelle, les opérations par lots constituent une technologie clé pour améliorer les performances et l'efficacité. Bleve offre un mécanisme complet d'indexation par lots. Grâce au contrôle approprié de la taille des lots, au traitement concurrent et à la gestion de la mémoire, il est possible d'améliorer considérablement la vitesse de construction des index.

Mécanisme central de l'indexation par lots

L'indexation par lots de Bleve utilise la structure Batch, qui combine plusieurs opérations d'indexation et de suppression, les exécutant en une seule transaction. Ce mécanisme réduit le nombre d'opérations d'E/S disque et les conflits de verrouillage, particulièrement adapté aux scénarios d'importation de données à grande échelle.

// Exemple de création d'index par lots
lot := index.NouveauLot()

// Ajouter des documents en lots
for i, element := range elements {
    lot.Indexer(fmt.Sprintf("document-%d", i), element)
    // Soumettre le lot tous les 1000 documents
    if lot.Taille() >= 1000 {
        err := index.Lot(lot)
        if err != nil {
            log.Printf("Échec de l'indexation par lots : %v", err)
        }
        lot.Reinitialiser()  // Réinitialiser le lot pour continuer
    }
}

// Soumettre les documents restants
if lot.Taille() > 0 {
    err := index.Lot(lot)
    if err != nil {
        log.Printf("Échec de la soumission du lot final : %v", err)
    }
}

Stratégies d'optimisation de la taille des lots

Le choix de la taille des lots affecte directement les performances d'indexation. La taille par défaut de Bleve est de 1000, mais elle doit être ajustée dynamiquement selon les caractéristiques des données et la configuration matérielle :

Gestion de la mémoire et surveillance des performances

L'indexation par lots à grande échelle nécessite une attention particulière à l'utilisation de la mémoire. Bleve propose des interfaces de surveillance de la mémoire :

// Surveillance mémoire et ajustement adaptatif
func indexationAdaptative(index bleve.Index, elements []interface{}) error {
    lot := index.NouveauLot()
    tailleLotOptimale := 1000
    memoireMaxMo := 512  // Définir la limite de mémoire maximale
    
    for i, element := range elements {
        lot.Indexer(fmt.Sprintf("document-%d", i), element)
        
        // Surveiller l'utilisation de la mémoire
        if lot.TailleTotaleDocuments() > uint64(memoireMaxMo*1024*1024) {
            // Mémoire dépassée, soumettre immédiatement et réduire la taille du lot
            if err := index.Lot(lot); err != nil {
                return err
            }
            lot.Reinitialiser()
            tailleLotOptimale = max(100, tailleLotOptimale/2)  // Réduire la taille du lot
        }
        
        if lot.Taille() >= tailleLotOptimale {
            if err := index.Lot(lot); err != nil {
                return err
            }
            lot.Reinitialiser()
            // Ajuster dynamiquement la taille du lot selon les performances
            tailleLotOptimale = min(5000, tailleLotOptimale+100)
        }
    }
    
    // Soumettre les documents restants
    if lot.Taille() > 0 {
        return index.Lot(lot)
    }
    return nil
}

Modèles de traitement concurrent par lots

Pour les ensembles de données ultra-volumineux, un modèle de traitement concurrent par lots peut être adopté pour充分利用 les ressources CPU multicœurs :

// Processeur d'indexation concurrent par lots
type IndexeurConcurrent struct {
    index         bleve.Index
    tailleLot     int
    workers       int
    fileAttente   chan interface{}
    groupeAttente sync.WaitGroup
    canalErreurs  chan error
}

func NouveauIndexeurConcurrent(index bleve.Index, tailleLot, workers int) *IndexeurConcurrent {
    return &IndexeurConcurrent{
        index:        index,
        tailleLot:    tailleLot,
        workers:      workers,
        fileAttente:  make(chan interface{}, 10000),
        canalErreurs: make(chan error, workers),
    }
}

func (c *IndexeurConcurrent) Demarrer() {
    for i := 0; i < c.workers; i++ {
        c.groupeAttente.Add(1)
        go c.travailleur(i)
    }
}

func (c *IndexeurConcurrent) travailleur(id int) {
    defer c.groupeAttente.Done()
    lot := c.index.NouveauLot()
    compteur := 0
    
    for element := range c.fileAttente {
        idDocument := fmt.Sprintf("document-%d-%d", id, compteur)
        if err := lot.Indexer(idDocument, element); err != nil {
            c.canalErreurs <- fmt.Errorf("travailleur %d : %v", id, err)
            return
        }
        compteur++
        
        if lot.Taille() >= c.tailleLot {
            if err := c.index.Lot(lot); err != nil {
                c.canalErreurs <- fmt.Errorf("travailleur %d soumission lot : %v", id, err)
                return
            }
            lot.Reinitialiser()
        }
    }
    
    // Soumettre les documents restants
    if lot.Taille() > 0 {
        if err := c.index.Lot(lot); err != nil {
            c.canalErreurs <- err
        }
    }
}

Gestion des erreurs et mécanisme de reprise

L'indexation par lots à grande échelle doit inclure une gestion des erreurs robuste et un mécanisme de reprise :

// Fonction de soumission par lots avec reprise
func soumettreAvecReprise(index bleve.Index, lot *bleve.Lot, tentativesMax int) error {
    var derniereErreur error
    
    for tentative := 0; tentative < tentativesMax; tentative++ {
        if tentative > 0 {
            time.Sleep(time.Duration(tentative*tentative) * time.Second) // Recul exponentiel
        }
        
        if err := index.Lot(lot); err != nil {
            derniereErreur = err
            log.Printf("Échec de la soumission par lots tentative %d : %v", tentative+1, err)
            continue
        }
        return nil
    }
    
    return fmt.Errorf("Échec de la soumission par lots après %d tentatives : %v", tentativesMax, derniereErreur)
}

// Gestion des erreurs au niveau du document
func indexationSecurisee(lot *bleve.Lot, idDocument string, donnees interface{}) error {
    defer func() {
        if r := recover(); r != nil {
            log.Printf("Panic lors de l'indexation du document %s : %v", idDocument, r)
        }
    }()
    
    return lot.Indexer(idDocument, donnees)
}

Surveillance des indicateurs de performance

Établir un système complet de surveillance des performances pour suivre en temps réel les indicateurs clés de l'indexation par lots :

Indicateur de surveillance Description Objectif d'optimisation
Temps de soumission de lot Durée de soumission d'un lot unique < 500ms
Pic d'utilisation mémoire Utilisation mémoire pendant le traitement des lots < 80% de la mémoire système
Débit E/S disque Vitesse d'écriture de l'index sur disque Correspondre aux performances de stockage
Utilisation CPU Utilisation CPU pendant le traitement de l'index 70-90%
Débit de traitement des documents Nombre de documents traités par seconde Maximiser le débit
// Structure de surveillance des performances
type MetriquesIndexation struct {
    Debut              time.Time
    DocumentsTotaux    int64
    DocumentsTermines  int64
    NombreLots         int64
    DureeTotale        time.Duration
    DureeLotMax        time.Duration
    DureeLotMin        time.Duration
    DureeLotTotale     time.Duration
    PicMemoire         uint64
}

// Surveillance des performances en temps réel
func surveillerPerformances(metriques *MetriquesIndexation, tailleLot int, tempsLot time.Duration) {
    metriques.NombreLots++
    metriques.DocumentsTermines += int64(tailleLot)
    metriques.DureeLotTotale += tempsLot
    
    if tempsLot > metriques.DureeLotMax {
        metriques.DureeLotMax = tempsLot
    }
    if metriques.DureeLotMin == 0 || tempsLot < metriques.DureeLotMin {
        metriques.DureeLotMin = tempsLot
    }
    
    // Sortie en temps réel des indicateurs de performance
    if metriques.NombreLots%10 == 0 {
        tempsLotMoyen := time.Duration(int64(metriques.DureeLotTotale) / metriques.NombreLots)
        documentsParSec := float64(metriques.DocumentsTermines) / time.Since(metriques.Debut).Seconds()
        
        log.Printf("Indicateurs de performance : %d/%d documents traités, temps moyen de lot : %v, débit : %.1f documents/seconde",
            metriques.DocumentsTermines, metriques.DocumentsTotaux, tempsLotMoyen, documentsParSec)
    }
}

En appliquant ces meilleures pratiques, vous pouvez construire une solution d'indexation par lots de données à grande échelle efficace et stable, exploitant pleinement les avantages de Bleve en termes de performances dans les scénarios de forte concurrence et de gros volume de données.

Stratégies de déploiement de Bleve en environnement distribué

Lors de la construction d'une solution de recherche d'entreprise, le déploiement distribué est essentiel pour garantir la haute disponibilité, l'évolutivité et la tolérance aux pannes. Bleve, en tant que bibliothèque d'indexation textuelle moderne écrite en Go, ne fournit pas nativement de fonctionnalités distribées. Cependant, grâce à une conception architecturale appropriée et l'utilisation d'outils externes, il est tout à fait possible de construire un système de recherche distribué puissant.

Étiquettes: bleve RECHERCHE golang moteurs-recherche Indexation

Publié le 1 juillet à 02h02