···11+-- Create GIN index on the tags array in the JSONB data field
22+-- This allows efficient querying of documents by tag
33+CREATE INDEX IF NOT EXISTS idx_documents_tags
44+ ON "public"."documents" USING gin ((data->'tags'));
55+66+-- Function to search and aggregate tags from documents
77+-- This does the aggregation in the database rather than fetching all documents
88+CREATE OR REPLACE FUNCTION search_tags(search_query text)
99+RETURNS TABLE (name text, document_count bigint) AS $$
1010+BEGIN
1111+ RETURN QUERY
1212+ SELECT
1313+ LOWER(tag::text) as name,
1414+ COUNT(DISTINCT d.uri) as document_count
1515+ FROM
1616+ "public"."documents" d,
1717+ jsonb_array_elements_text(d.data->'tags') as tag
1818+ WHERE
1919+ CASE
2020+ WHEN search_query = '' THEN true
2121+ ELSE LOWER(tag::text) LIKE '%' || search_query || '%'
2222+ END
2323+ GROUP BY
2424+ LOWER(tag::text)
2525+ ORDER BY
2626+ COUNT(DISTINCT d.uri) DESC,
2727+ LOWER(tag::text) ASC
2828+ LIMIT 20;
2929+END;
3030+$$ LANGUAGE plpgsql STABLE;