选择仅包含 N 个标签的文章

我有两个实体,文章实体和标签实体。这两个实体之间存在 ManyToMany 关系(一篇文章可以有 0->N 个标签,一个标签可以包含在 0->N 篇文章中)


我想要在某些条件下搜索文章(我必须使用查询生成器,像 findBy() 这样的魔术方法还不够),这些条件之一是选择恰好包含 N 个特定标签的文章


我尝试了几次以获得预期的结果但没有成功。我想我误解了学说如何与连接表一起工作。我最后一次尝试:


public function search($titles, $tags, $authors)

{


    $query = $this->createQueryBuilder('a') // a = article

        ->orderBy('a.createdAt', 'DESC')

        ->setMaxResults($limit)

        ->setFirstResult($offset);


    if($titles !== null){

        // ...

    }


    // tags is an array of string containing names of searched tags (ex : $tags = ['english', 'french', 'game', 'guide'] )

    if($tags !== null){

        // $query->innerJoin('a.tags', 't');

        // $tagsQuery = "";

        // foreach ($tags as $id => $tag){

        //     if($id > 0) $tagsQuery .= " AND ";

        //     $tagsQuery .= "t.name LIKE :tag_".$id;

        //     $query->setParameter("tag_".$id, '%'.$tag.'%');

        // }

        // $query

        //     ->andWhere($tagsQuery);


        $query->leftjoin ('a.tags','t');

        foreach ($tags as $id => $tag){

        // $query->andWhere("t.name LIKE :tag_".$id);

        // $query->setParameter("tag_".$id, '%'.$tag.'%');

            $query

                ->addSelect('t')

                ->andwhere("t.name LIKE :tag_".$id)

                ->setParameter("tag_".$id, '%'.$tag.'%');

        }

    }


    // ...

预期结果的示例:


有 3 篇文章:


- id 1 

- tags : 

    - guide

    - game


- id 2 

- tags : 

    - english


- id 3 

- tags : 

    - english

    - guide

该方法search(null, ['guide','english'], null)必须只返回 id 为 3 的文章


潇潇雨雨
浏览 108回答 2
2回答

蝴蝶刀刀

如果你想让所有文章都至少有一个指定的标签,你的代码应该是这样的:    public function search($titles, $tags, $authors)    {        return $query = $this->createQueryBuilder('a') // a = article            ->innerJoin('a.tags', 't') //on inner join is enough            ->where('t.name in (:set)')            ->setParameter('set', $tags)            ->orderBy('a.createdAt', 'DESC')            ->setMaxResults($limit)            ->setFirstResult($offset)            ->getQuery()   //retrieve            ->getResult();    }第一个 SQL 将进行连接。提示是使用“in”运算符。如果您想要包含所有标签(完全是所有)的文章,您应该为每个标签添加一个内部连接。技巧是为每个连接添加一个别名,并在别名上添加一个唯一的东西。    public function search($titles, $tags, $authors)    {        $query = $this->createQueryBuilder('a') // a = article;        foreach ($tags as $index => $tag) {             $query->innerJoin('a.tags', "t$index")               ->andWhere("t$index" + ".name in (:tag$index)")               ->setParameter("tag$index", $tag)        }        return $query            ->orderBy('a.createdAt', 'DESC')            ->setMaxResults($limit)            ->setFirstResult($offset)            ->getQuery()   //retrieve            ->getResult();你的要求应该是这样的。我没有测试它们,但这是模板。

慕雪6442864

如果有人有同样的问题,这里的代码:     foreach ($tags as $id => $tag) {            $query->innerJoin('a.tags', "t${id}")                ->andWhere("t${id}.name in (:tag${id})")                ->setParameter(":tag${id}", $tag);     }
打开App,查看更多内容
随时随地看视频慕课网APP