SPB Git

spb/trouve-ka Public

Trouve-KA — moteur de recherche web indépendant, Québec-first. Crawler distribué, index OpenSearch, ranking bilingue, galerie d'images. En prod : www.trouve-ka.com

Python 76.8% TypeScript 15.7% SQL 3.9% Shell 1.4% CSS 1.3% Dockerfile 0.7%
2.2 KB · 67 lines python
Raw Blame History
1# Trouve-KA — client OpenSearch2# Author: Simon-Pierre Boucher3# Contact: contact@spboucher.ai45"""Client OpenSearch async : création d'index, indexation immédiate, recherche, statut."""67import hashlib8from typing import Any910from opensearchpy import AsyncOpenSearch11from opensearchpy.exceptions import NotFoundError1213from .mapping import INDEX_SETTINGS141516def doc_id_for_url(url: str) -> str:17    """ID de document stable dérivé de l'URL canonique."""18    return hashlib.sha256(url.encode("utf-8")).hexdigest()[:32]192021class SearchCore:22    def __init__(self, search_url: str, index: str):23        self.index = index24        self.client = AsyncOpenSearch(hosts=[search_url], timeout=15, max_retries=2, retry_on_timeout=True)2526    async def close(self) -> None:27        await self.client.close()2829    async def ensure_index(self) -> None:30        if not await self.client.indices.exists(index=self.index):31            await self.client.indices.create(index=self.index, body=INDEX_SETTINGS)3233    async def index_document(self, doc: dict[str, Any]) -> str:34        """Indexation immédiate d'un document (cherchable au prochain refresh, ~1 s)."""35        _id = doc_id_for_url(doc["canonical_url"] or doc["url"])36        await self.client.index(index=self.index, id=_id, body=doc)37        return _id3839    async def update_document(self, url: str, partial: dict[str, Any]) -> None:40        """Mise à jour partielle (enrichissement asynchrone, étapes 2-3)."""41        try:42            await self.client.update(index=self.index, id=doc_id_for_url(url), body={"doc": partial})43        except NotFoundError:44            pass4546    async def delete_document(self, url: str) -> None:47        try:48            await self.client.delete(index=self.index, id=doc_id_for_url(url))49        except NotFoundError:50            pass5152    async def search(self, body: dict[str, Any]) -> dict[str, Any]:53        return await self.client.search(index=self.index, body=body)5455    async def count(self) -> int:56        try:57            res = await self.client.count(index=self.index)58            return res["count"]59        except NotFoundError:60            return 06162    async def ping(self) -> bool:63        try:64            return await self.client.ping()65        except Exception:66            return False67