为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

PHP
潇潇雨雨 2022-12-11 10:12:43
我有两个实体,文章实体和标签实体。这两个实体之间存在 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 的文章
查看完整描述

2 回答

?
蝴蝶刀刀

TA贡献1801条经验 获得超8个赞

如果你想让所有文章都至少有一个指定的标签,你的代码应该是这样的:


    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();

你的要求应该是这样的。我没有测试它们,但这是模板。


查看完整回答
反对 回复 2022-12-11
?
慕雪6442864

TA贡献1812条经验 获得超5个赞

如果有人有同样的问题,这里的代码:


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

            $query->innerJoin('a.tags', "t${id}")

                ->andWhere("t${id}.name in (:tag${id})")

                ->setParameter(":tag${id}", $tag);

     }


查看完整回答
反对 回复 2022-12-11
  • 2 回答
  • 0 关注
  • 98 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信