0

スキーマ:

カテゴリ [、、、、、、、、] id_ parent_ children_ left_ right_levelrootproducts

製品 [id、、category]marketSegments

MarketSegment [ id ]

また、各エンティティには、、など nameのフィールドがありますが description slug これらは私の問題には関係ありません。

サンプルデータ

伝説:

c-カテゴリ、p-製品

*でマークされた製品は、市場セグメント「ExporttoUSA」でタグ付けされています

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]

期待されるクエリ結果:

与えられたデータと$category = Food$ marketSegment = Export to USAの場合、期待される結果は次のようになります。

$filteredCategories = [Fruits, Meat]

なんで?

  • MeatBeefこれは、ExporttoUSAでタグ付けされた製品が含まれているためです。
  • Fruitsタグ付けされた製品を含むカテゴリHesperidiumsが含まれているためです。

ネストされたツリーの深さは、タグ付けされた製品を含むカテゴリに関係ありません。

これ:

Sports [c]
-----> Individual [c]
----------------> Fight [c]
----------------------> MMA [c]
--------------------------> Boxing gloves* [p]

$ category = Sportsの場合:[ Individual]を返す必要があります。

$ category = Fightの場合は次を返す必要があります:[ MMA]。


私の(機能していない)DQLアプローチ:

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
4

2 に答える 2

3

NestedTreeRepositoryGedmo NestedSet動作拡張機能に同梱されているものにはgetChildrenQueryBuilder()、親ノードを指定して子をクエリできるメソッドと、階層の数層深いノードをクエリするためのパラメーターがあります。NestedTreeRepositoryDQLを手動で作成する必要がないように、付属のメソッドとオプションを調査する必要があります。

すべてのコードがどのように設定されているか完全にはわからないため、正確な解決策を提供することはできませんが、理解できると思います:)

NestedSetのドキュメント: http: //www.gediminasm.org/article/tree-nestedset-behavior-extension-for-doctrine-2

于 2012-11-28T00:00:58.123 に答える
1

ジョンありがとう!NestedTreeRepositoryを使用して、解決策を見つけました。

NestedTreeRepositoryを拡張するCategoryクラスの独自のリポジトリを作成し、カスタムメソッドを作成しました

パブリック関数findSubcategoriesFilteredByMarketSegment(Category $ parentNode、MarketSegment $ segment)

{{

   // get DIRECT CHILDREN for $parentNode
   $qb = $this->getChildrenQueryBuilder($parentNode, true);
   $qb->leftJoin($qb->getRootAlias().'.products', 'prod')
      ->leftJoin('prod.marketSegments', 'seg');    

   // subquery -> get all children (direct and indirect) 
   // for DIRECT CHILD from main query
   $sqb = $this->_em->getRepository('AvocodeCatalogBundle:Category')->createQueryBuilder('sub');

   // join products and market segments
   $sqb->leftJoin($sqb->getRootAlias().'.products', 'sub_prod')
       ->leftJoin('sub_prod.marketSegments', 'sub_seg');

   // to match children of main query's DIRECT CHILD
   // they need to have left and right values between DIRECT CHILD's left and right
   $sqb->where(
            $sqb->expr()->andX(
               $sqb->expr()->gt('sub.lft', $qb->getRootAlias().'.lft'),
               $sqb->expr()->lt('sub.rgt', $qb->getRootAlias().'.rgt'),
               $sqb->expr()->eq('sub.root', $qb->getRootAlias().'.root')
        ));

   // match only children with products related to $segment
   $sqb->andWhere($sqb->expr()->eq('sub_seg.id', ':segment_id'));

   // BACK TO MAIN QUERY
   // select only parentNode children THAT
   $qb->andWhere(
         $qb->expr()->orX(
             // contain product with related segment
             $qb->expr()->eq('seg.id', ':segment_id'),
             // or 
             // have a child (direct or indirect) that does contain such product
             $qb->expr()->exists($sqb->getDQL())       
     ))
     ->setParameter('segment_id', $segment->getId());

   return $qb->getQuery()->getResult();

}

于 2012-11-29T12:45:58.227 に答える