Backup #773
| ID | 773 |
| Dateipfad | /var/www/dev.campus.systemische-tools.de/src/Infrastructure/Persistence/CollectionRepository.php |
| Version | 4 |
| Typ |
modified |
| Größe | 6.9 KB |
| Hash | e2d729fe6163ec5d8f019848b27a6f60f4ee405ce79386fee4748398bd44ae79 |
| Datum | 2025-12-23 08:04:45 |
| Geändert von | claude-code-hook |
| Grund | Claude Code Pre-Hook Backup vor Edit-Operation |
| Datei existiert |
Ja
|
Dateiinhalt
<?php
declare(strict_types=1);
namespace Infrastructure\Persistence;
use Domain\Repository\CollectionRepositoryInterface;
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 implements CollectionRepositoryInterface
{
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
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