Backup #248

ID248
Dateipfad/var/www/dev.campus.systemische-tools.de/src/Infrastructure/Persistence/CollectionRepository.php
Version3
Typ modified
Größe6.8 KB
Hash6d4e536d6355c3ce444feebdcb12064715b9272891ae95ec245ef06e207ed5cd
Datum2025-12-22 01:48:51
Geändert vonclaude-code-hook
GrundClaude Code Pre-Hook Backup vor Edit-Operation
Datei existiert Ja

Dateiinhalt

<?php

declare(strict_types=1);

namespace Infrastructure\Persistence;

use Infrastructure\Config\DatabaseFactory;
use PDO;

/**
 * Repository for RAG collections stored in ki_dev.rag_collections.
 *
 * Provides access to collection metadata synced from Qdrant.
 * Used for dropdown population and dimension validation.
 *
 * @package Infrastructure\Persistence
 */
final class CollectionRepository
{
    private PDO $pdo;

    public function __construct(?PDO $pdo = null)
    {
        $this->pdo = $pdo ?? DatabaseFactory::dev();
    }

    /**
     * Find a collection by its Qdrant collection_id.
     *
     * @return array<string, mixed>|null
     */
    public function find(string $collectionId): ?array
    {
        $stmt = $this->pdo->prepare('
            SELECT * FROM rag_collections
            WHERE collection_id = ?
        ');
        $stmt->execute([$collectionId]);
        $result = $stmt->fetch(PDO::FETCH_ASSOC);

        return $result ?: null;
    }

    /**
     * Find multiple collections by their IDs.
     *
     * @param array<string> $collectionIds
     * @return array<int, array<string, mixed>>
     */
    public function findByIds(array $collectionIds): array
    {
        if (empty($collectionIds)) {
            return [];
        }

        $placeholders = implode(',', array_fill(0, count($collectionIds), '?'));
        $stmt = $this->pdo->prepare("
            SELECT * FROM rag_collections
            WHERE collection_id IN ($placeholders)
        ");
        $stmt->execute($collectionIds);

        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    /**
     * Get all active and searchable collections for dropdowns.
     *
     * @return array<int, array<string, mixed>>
     */
    public function getSearchable(): array
    {
        $stmt = $this->pdo->query('
            SELECT collection_id, display_name, points_count, vector_size
            FROM rag_collections
            WHERE is_active = 1 AND is_searchable = 1
            ORDER BY sort_order ASC, display_name ASC
        ');

        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    /**
     * Get all active collections (including non-searchable).
     *
     * @return array<int, array<string, mixed>>
     */
    public function getActive(): array
    {
        $stmt = $this->pdo->query('
            SELECT collection_id, display_name, points_count, vector_size, is_searchable
            FROM rag_collections
            WHERE is_active = 1
            ORDER BY sort_order ASC, display_name ASC
        ');

        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    /**
     * Get all collections (for admin).
     *
     * @return array<int, array<string, mixed>>
     */
    public function getAll(): array
    {
        $stmt = $this->pdo->query('
            SELECT * FROM rag_collections
            ORDER BY sort_order ASC, display_name ASC
        ');

        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    /**
     * Check if a collection exists.
     */
    public function exists(string $collectionId): bool
    {
        $stmt = $this->pdo->prepare('
            SELECT 1 FROM rag_collections WHERE collection_id = ?
        ');
        $stmt->execute([$collectionId]);

        return $stmt->fetchColumn() !== false;
    }

    /**
     * Update collection metadata (from Qdrant sync).
     *
     * @param array<string, mixed> $data
     */
    public function updateMetadata(string $collectionId, array $data): void
    {
        $allowed = ['vector_size', 'distance_metric', 'points_count', 'last_synced_at'];
        $updates = [];
        $params = [];

        foreach ($allowed as $field) {
            if (array_key_exists($field, $data)) {
                $updates[] = "$field = ?";
                $params[] = $data[$field];
            }
        }

        if (empty($updates)) {
            return;
        }

        $params[] = $collectionId;
        $sql = 'UPDATE rag_collections SET ' . implode(', ', $updates) . ' WHERE collection_id = ?';
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
    }

    /**
     * Create a new collection entry.
     *
     * @param array<string, mixed> $data
     */
    public function create(array $data): int
    {
        $stmt = $this->pdo->prepare('
            INSERT INTO rag_collections
            (collection_id, display_name, description, vector_size, distance_metric,
             points_count, embedding_model, source_type, is_active, is_searchable, sort_order)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        ');

        $stmt->execute([
            $data['collection_id'],
            $data['display_name'] ?? $data['collection_id'],
            $data['description'] ?? null,
            $data['vector_size'] ?? null,
            $data['distance_metric'] ?? 'Cosine',
            $data['points_count'] ?? 0,
            $data['embedding_model'] ?? null,
            $data['source_type'] ?? 'manual',
            $data['is_active'] ?? true,
            $data['is_searchable'] ?? true,
            $data['sort_order'] ?? 0,
        ]);

        return (int) $this->pdo->lastInsertId();
    }

    /**
     * Deactivate a collection (soft delete).
     */
    public function deactivate(string $collectionId): void
    {
        $stmt = $this->pdo->prepare('
            UPDATE rag_collections
            SET is_active = 0, is_searchable = 0
            WHERE collection_id = ?
        ');
        $stmt->execute([$collectionId]);
    }

    /**
     * Check if collection is referenced by sessions, orders, or preferences.
     *
     * @return array{has_references: bool, references: array<int, array{type: string, count: int}>}
     */
    public function checkReferences(string $collectionId): array
    {
        $references = [];
        $jsonValue = json_encode($collectionId);

        // Check chat_sessions (ki_content)
        try {
            $pdo = DatabaseFactory::content();
            $stmt = $pdo->prepare("
                SELECT COUNT(*) FROM chat_sessions
                WHERE JSON_CONTAINS(collections, ?, '$')
            ");
            $stmt->execute([$jsonValue]);
            $count = (int) $stmt->fetchColumn();
            if ($count > 0) {
                $references[] = ['type' => 'chat_sessions', 'count' => $count];
            }

            // Check content_orders (ki_content)
            $stmt = $pdo->prepare("
                SELECT COUNT(*) FROM content_orders
                WHERE JSON_CONTAINS(collections, ?, '$')
            ");
            $stmt->execute([$jsonValue]);
            $count = (int) $stmt->fetchColumn();
            if ($count > 0) {
                $references[] = ['type' => 'content_orders', 'count' => $count];
            }
        } catch (\PDOException $e) {
            // Tables might not exist yet
        }

        return [
            'has_references' => count($references) > 0,
            'references' => $references,
        ];
    }
}

Vollständig herunterladen

Aktionen

Herunterladen

Andere Versionen dieser Datei

ID Version Typ Größe Datum
1207 8 modified 6.8 KB 2025-12-25 10:35
1206 7 modified 6.7 KB 2025-12-25 10:35
1198 6 modified 6.7 KB 2025-12-25 10:34
1181 5 modified 6.7 KB 2025-12-25 10:32
773 4 modified 6.9 KB 2025-12-23 08:04
248 3 modified 6.8 KB 2025-12-22 01:48
194 2 modified 6.8 KB 2025-12-21 14:38
193 1 modified 6.8 KB 2025-12-21 14:38

← Zurück zur Übersicht