[ 'properties' => [ 'identifiant' => ['type' => 'keyword'], 'type' => ['type' => 'keyword'], 'titre' => ['type' => 'text', 'analyzer' => 'french'], 'contenu' => ['type' => 'text', 'analyzer' => 'french'], ], ], ]); $documents = Lab::all() ->map(fn (Lab $lab) => [ 'identifiant' => $lab->identifiant, 'type' => 'lab', 'titre' => $lab->titre, 'contenu' => trim($lab->titre.' '.implode(' ', $lab->competences ?? [])), ]) ->concat(Cours::all()->map(fn (Cours $cours) => [ 'identifiant' => $cours->identifiant, 'type' => 'cours', 'titre' => $cours->titre, 'contenu' => trim($cours->titre.' '.self::texteBrut($cours->contenu_markdown)), ])); foreach ($documents as $document) { Http::put(self::url("/_doc/{$document['type']}-{$document['identifiant']}"), $document); } } /** * @return array */ public static function chercher(string $texte): array { if (! self::disponible() || trim($texte) === '') { return []; } $reponse = Http::post(self::url('/_search'), [ 'query' => ['multi_match' => ['query' => $texte, 'fields' => ['titre^3', 'contenu']]], 'highlight' => ['fields' => ['contenu' => new \stdClass]], 'size' => 20, ]); if ($reponse->failed()) { return []; } /** @var array> $resultats */ $resultats = $reponse->json('hits.hits') ?? []; return collect($resultats) ->map(fn (array $hit) => [ 'type' => $hit['_source']['type'], 'identifiant' => $hit['_source']['identifiant'], 'titre' => $hit['_source']['titre'], 'extrait' => $hit['highlight']['contenu'][0] ?? Str::limit($hit['_source']['contenu'], 200), ]) ->all(); } private static function url(string $chemin = ''): string { return 'http://'.config('elasticsearch.hote').':'.config('elasticsearch.port').'/'.config('elasticsearch.index').$chemin; } private static function texteBrut(string $markdown): string { return trim(preg_replace('/[#*`_\[\]()>-]/', ' ', $markdown) ?? ''); } }