Schema:
Category [
id
,parent
,children
,left
,right
,level
,root
,products
]Product [
id
,category
,marketSegments
]MarketSegment [
id
]Also each entity has fields like
name
,description
,slug
but those are not relevant to my issue.
Example data
Legend:
c
- Category, p
- Product
Products marked with * are tagged with market segment "Export to USA"
Food [c, id: 1, level: 0]
---> Vegetables [c, id: 2, level: 1]
--------------> Potato [p, id: 1]
--------------> Carrot [p, id: 2]
---> Fruits [c, id: 3, level: 1]
--------------> Berries [c, id: 5, level: 2]
---------------------------> Grapes [p, id: 3]
--------------> Hesperidiums [c, id: 6, level: 2]
---------------------------> Orange* [p, id: 4]
---> Meat [c, id: 4, level: 1]
--------------> Beef* [p, id: 5]
Expected query result:
For given data and $category = Food, $marketSegment = Export to USA the expected result would be:
$filteredCategories = [Fruits, Meat]
Why?
Meat
becouse it contains productBeef
which is tagged with Export to USAFruits
becouse it contains categoryHesperidiums
which contains a tagged product.
It does not matter how deep in the nested tree the category containing tagged product is.
This:
Sports [c]
-----> Individual [c]
----------------> Fight [c]
----------------------> MMA [c]
--------------------------> Boxing gloves* [p]
For $category = Sports should return: [ Individual
].
For $category = Fight should return: [ MMA
].
My (not working) DQL approach:
SELECT DISTINCT cat FROM Avocode\CatalogBundle\Entity\Category cat
WHERE cat.parent = :parent_id
AND (EXISTS(
SELECT sub FROM Avocode\CatalogBundle\Entity\Category sub
LEFT JOIN sub.products prod
LEFT JOIN prod.marketSegments seg
WHERE sub.left > cat.left
AND sub.right < cat.right
AND seg.id = :segment_id
))
ORDER BY cat.root, cat.left ASC