fix: paginate Immich photo search — no longer limited to 200 — closes #137

The Immich metadata search was hardcoded to size: 200. Now paginates
through all results (1000 per page, up to 20k photos max).
This commit is contained in:
Maurice
2026-03-30 13:36:04 +02:00
parent 1166a09835
commit 7201380504
+14 -2
View File
@@ -77,6 +77,11 @@ router.post('/search', authenticate, async (req: Request, res: Response) => {
if (!user?.immich_url || !user?.immich_api_key) return res.status(400).json({ error: 'Immich not configured' }); if (!user?.immich_url || !user?.immich_api_key) return res.status(400).json({ error: 'Immich not configured' });
try { try {
// Paginate through all results (Immich limits per-page to 1000)
const allAssets: any[] = [];
let page = 1;
const pageSize = 1000;
while (true) {
const resp = await fetch(`${user.immich_url}/api/search/metadata`, { const resp = await fetch(`${user.immich_url}/api/search/metadata`, {
method: 'POST', method: 'POST',
headers: { 'x-api-key': user.immich_api_key, 'Content-Type': 'application/json' }, headers: { 'x-api-key': user.immich_api_key, 'Content-Type': 'application/json' },
@@ -84,13 +89,20 @@ router.post('/search', authenticate, async (req: Request, res: Response) => {
takenAfter: from ? `${from}T00:00:00.000Z` : undefined, takenAfter: from ? `${from}T00:00:00.000Z` : undefined,
takenBefore: to ? `${to}T23:59:59.999Z` : undefined, takenBefore: to ? `${to}T23:59:59.999Z` : undefined,
type: 'IMAGE', type: 'IMAGE',
size: 200, size: pageSize,
page,
}), }),
signal: AbortSignal.timeout(15000), signal: AbortSignal.timeout(15000),
}); });
if (!resp.ok) return res.status(resp.status).json({ error: 'Search failed' }); if (!resp.ok) return res.status(resp.status).json({ error: 'Search failed' });
const data = await resp.json() as { assets?: { items?: any[] } }; const data = await resp.json() as { assets?: { items?: any[] } };
const assets = (data.assets?.items || []).map((a: any) => ({ const items = data.assets?.items || [];
allAssets.push(...items);
if (items.length < pageSize) break; // Last page
page++;
if (page > 20) break; // Safety limit (20k photos max)
}
const assets = allAssets.map((a: any) => ({
id: a.id, id: a.id,
takenAt: a.fileCreatedAt || a.createdAt, takenAt: a.fileCreatedAt || a.createdAt,
city: a.exifInfo?.city || null, city: a.exifInfo?.city || null,