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 product Beef
which is tagged with Export to USA
Fruits
becouse it contains category Hesperidiums
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