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

View File

@@ -77,20 +77,32 @@ 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' });
try {
const resp = await fetch(`${user.immich_url}/api/search/metadata`, {
method: 'POST',
headers: { 'x-api-key': user.immich_api_key, 'Content-Type': 'application/json' },
body: JSON.stringify({
takenAfter: from ? `${from}T00:00:00.000Z` : undefined,
takenBefore: to ? `${to}T23:59:59.999Z` : undefined,
type: 'IMAGE',
size: 200,
}),
signal: AbortSignal.timeout(15000),
});
if (!resp.ok) return res.status(resp.status).json({ error: 'Search failed' });
const data = await resp.json() as { assets?: { items?: any[] } };
const assets = (data.assets?.items || []).map((a: any) => ({
// 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`, {
method: 'POST',
headers: { 'x-api-key': user.immich_api_key, 'Content-Type': 'application/json' },
body: JSON.stringify({
takenAfter: from ? `${from}T00:00:00.000Z` : undefined,
takenBefore: to ? `${to}T23:59:59.999Z` : undefined,
type: 'IMAGE',
size: pageSize,
page,
}),
signal: AbortSignal.timeout(15000),
});
if (!resp.ok) return res.status(resp.status).json({ error: 'Search failed' });
const data = await resp.json() as { assets?: { items?: 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,
takenAt: a.fileCreatedAt || a.createdAt,
city: a.exifInfo?.city || null,