1

Doctrine2 と MySQL で Symfony2 を使用しています。

2 つのエンティティを作成しました。

  • 論文
  • それらの間の多対多リンクでタグ付けします。

タグの ID のリストから、記事の OR と AND を取得しようとしています。

例はより良いかもしれません:

  • 記事 1 <-> タグ 1、タグ 2
  • Article2 <-> Tag2、Tag3、Tag4
  • Article3 <-> Tag1、Tag4

タグ [2, 3] の ID のリストから、AND および OR 要求を実行して、いくつかの記事を取得します。

  • AND => 両方のタグを含むのは [Article2] だけです。
  • OR => [Article1, Article2] は、tag2 と tag3 を持つ唯一のものです。

PHPコードでループを使用して複数のリクエストを使用してORクエリを実行することに成功しましたが、これは実際にはまったく最適化されていません。そして、AND に対する要求の数で組み合わせ爆発を起こすことを恐れています。JOIN を使用して MySQL でそれを行う適切な方法があることは知っていますが、Doctrine2 言語も 1 つの要求で行うことができますが、ドキュメントを読んで試してみると、それが自分のコンピューティング レベルではないことがわかります。

誰かがこの点で私を助けることができれば、私は感謝します.

編集:最適化されていない私の現在のソリューションは次のとおりです。

class TagRepository extends EntityRepository
{
    public function getItemsFromIds($ids)
    {
        $qb = $this->createQueryBuilder('a');
        $qb->where('a.id IN (:ids)')
            ->setParameter('ids', $ids);

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

次に、私の DefaultController.php で、ものを処理する関数で:

$finalarticles = array();

$tagsrepository = $this->getDoctrine()
                   ->getEntityManager()
                   ->getRepository('ElephantTagsBundle:Tag');

$tags = $tagsrepository->getItemsFromIds($tagids);
$nbtags = count($tags);

foreach ($tags as $tag) {
    $articles = $tag->getArticles();
    foreach ($articles as $article) {
        $articlestags = $article->getTags();
        $tmpnbtags = 0;
        foreach ($articlestags as $articlestag) {
            if (in_array($articlestag->getId(), $tagids))
                $tmpnbtags += 1;
        }
        if ($tmpnbtags == $nbtags)
            $finalarticles[$article->getId()] = $article;
    }
}

ご覧のとおり、このメソッドには 3 つの for ループ (+1 つが "array_in" にあると思います) が含まれており、これには多くの MySQL 呼び出しも含まれています。リポジトリでそれを行う適切な方法があると確信しています!

4

1 に答える 1

0

resources/config フォルダからエンティティ定義を提供してください。あなたが探しているのはBidirectional Association Mappingです。ドキュメントを見てください:

http://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html#many-to-many-bidirectional

あなたの記事では:

<many-to-many target-entity="Tag" inversed-by="articles" field="articles"/>

そしてあなたのタグで:

<many-to-many field="articles" target-entity="Article" mapped-by="tags"/>

クラスが生成されると、タグまたは記事を両側から双方向に追加および取得できます。

記事からタグを削除したい場合は、次のように記事とタグ クラスにカスタム メソッドを実装する必要があります。

記事クラス:

public function removeTag(\YourBundle\Entity\Tag $tag){
        return $this->tags->removeElement($tag);
}

タグクラス:

public function removeArticle(\YourBundle\Entity\Article $article){
        return $this->articles->removeElement($article);
}
于 2012-09-25T13:10:59.233 に答える