查询构建器:多个AND表示为OR

时间:2017-05-09 13:59:19

标签: symfony doctrine-orm query-builder

实体Content和Filter之间有很多关系。 我想获得所有包含过滤器“1”,“2”和“3”(全部三个)的内容。我的查询给了我结果,好像我会使用“OR,因为我得到了很多只有三个过滤器中的一个的内容。

我的查询:

with open('file1.txt', 'r+') as file1, open('file2.txt') as file2:
    f1 = [i.strip() for i in file1.readlines()]
    f2 = [j.strip() for j in file2.readlines()]
    f1 += [item for item in f2 if item not in f1]
    file1.seek(0)
    for line in f1:
        file1.write(line + '\n')

实体内容:

public function getContentByFilters($categ, $filter, $filter2, $filter3){
    $query = $this->createQueryBuilder('c')
    ->leftJoin('c.filterfilter', 'f')
    ->where('f.idfilter = :filter_idfilter')
    ->setParameter('filter_idfilter', $filter)
    ->andWhere('f.idfilter = :filter_idfilter')
    ->setParameter('filter_idfilter', $filter2)
    ->andWhere('f.idfilter = :filter_idfilter')
    ->setParameter('filter_idfilter', $filter3)
    ->andWhere('c.contentCategorycontentCategory = ?2')
    ->setParameter(2, $categ)
    ->getQuery()->getResult();

    return $query;
}

}

实体过滤器:

/**
 * Content
 *
 * * @ORM\Entity(repositoryClass="loic\ContentBundle\Entity\ContentRepository")
 * @ORM\Table(name="content", uniqueConstraints={@ORM\UniqueConstraint(name="idcontent_UNIQUE", columns={"idcontent"})}, indexes={@ORM\Index(name="user_id", columns={"user_id"}), @ORM\Index(name="fk_content_content_category1_idx", columns={"content_category_idcontent_category"})})
 */
class Content
{
    /**
     * @var integer
     *
     * @ORM\Column(name="idcontent", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $idcontent;

.............
/**
 * @var \Doctrine\Common\Collections\Collection
 *
 * @ORM\ManyToMany(targetEntity="loic\FilterBundle\Entity\Filter", inversedBy="contentcontent")
 * @ORM\JoinTable(name="content_has_filter",
 *   joinColumns={
 *     @ORM\JoinColumn(name="content_idcontent", referencedColumnName="idcontent")
 *   },
 *   inverseJoinColumns={
 *     @ORM\JoinColumn(name="filter_idfilter", referencedColumnName="idfilter")
 *   }
 * )
 */
private $filterfilter;

/**
 * Constructor
 */
public function __construct()
{
    $this->contentLinked = new \Doctrine\Common\Collections\ArrayCollection();
    $this->filterfilter = new \Doctrine\Common\Collections\ArrayCollection();
    $this->creationDate = new \DateTime();
}

.........

/**
 *
 * @return the \Doctrine\Common\Collections\Collection
 */
public function getFilterfilter() {
    return $this->filterfilter;
}

/**
 *
 * @param
 *          $filterfilter
 */
public function setFilterfilter($filterfilter) {
    $this->filterfilter = $filterfilter;
    return $this;
}

1 个答案:

答案 0 :(得分:2)

由于您要检查3个过滤器,因此您需要JOIN 3次。就好像你有3个不同的ManyToMany关系,并且只想要一行,这符合3个特定要求 - 唯一的区别是,你加入同一个表。未经测试,但它应该像这样工作

$query = $this->createQueryBuilder('c')
    ->join('c.filterfilter', 'f1')
    ->join('c.filterfilter', 'f2')
    ->join('c.filterfilter', 'f3')
    ->where('f1.idfilter = :filter_idfilter1')
    ->andWhere('f2.idfilter = :filter_idfilter2')
    ->andWhere('f3.idfilter = :filter_idfilter3')
    ->andWhere('c.contentCategorycontentCategory = :category')
    ->setParameters(array(
        'filter_idfilter1' => $filter,
        'filter_idfilter2' => $filter2,
        'filter_idfilter3' => $filter3,
        'category' => $categ,
    ))
    ->getQuery()->getResult();

内部联接可能更好,因为您只需要满足这些要求的行。另外请注意,使用过多的连接通常被认为是不好的做法,可能会降低性能。首选解决方案通常是构建特定视图而不是多个连接。