Actually I came up with a query to do this. I already knew my recursion didn't go deeper than 3 or 4, so I played it safe at 6 levels, grouped by the concatenation of the parent categories (as some products started with multiple categories as well). This produces a result set that is the exact length as my number of products, and spits out the list of parent categories in a space-separated strings (to be used as tags).
SELECT
products.id,
products.name,
category_products.category_id,
GROUP_CONCAT(
CONCAT_WS(' ',
(select name from categories where id = c1.parent),
(select name from categories where id = c2.parent),
(select name from categories where id = c3.parent),
(select name from categories where id = c4.parent),
(select name from categories where id = c5.parent),
(select name from categories where id = c6.parent)
) SEPARATOR ' ') as parents,
(select name from categories where id = c1.parent) as c1parent,
(select name from categories where id = c2.parent) as c2parent,
(select name from categories where id = c3.parent) as c3parent,
(select name from categories where id = c4.parent) as c4parent,
(select name from categories where id = c5.parent) as c5parent,
(select name from categories where id = c6.parent) as c6parent
from products
LEFT JOIN category_products
LEFT JOIN category_relationships as c1 on category_products.category_id = c1.child
LEFT JOIN category_relationships as c2 on c2.child = c1.parent
LEFT JOIN category_relationships as c3 on c3.child = c2.parent
LEFT JOIN category_relationships as c4 on c4.child = c3.parent
LEFT JOIN category_relationships as c5 on c5.child = c4.parent
LEFT JOIN category_relationships as c6 on c6.child = c5.parent
on product_id = products.id
GROUP BY id;