查询构建器:多个 AND 就像一个 OR
Query builder: multiple AND act like an OR
我在实体内容和过滤器之间存在多对多关系。
我想获得所有具有过滤器“1”、“2”和“3”(全部三个)的内容。我的查询给我的结果就像我会使用“或”一样,因为我得到的很多内容只有三个过滤器之一。
我的查询:
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;
}
}
实体过滤器:
use Doctrine\ORM\Mapping as ORM;
/**
* Filter
*
* * @ORM\Entity(repositoryClass="loic\FilterBundle\Entity\FilterRepository")
* @ORM\Table(name="filter", uniqueConstraints={@ORM\UniqueConstraint(name="idfilter_UNIQUE", columns={"idfilter"})}, indexes={@ORM\Index(name="fk_filter_filter_category1_idx", columns={"filter_category_idfilter_category"})})
*/
class Filter
{
/**
* @var integer
*
* @ORM\Column(name="idfilter", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $idfilter;
............
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\ManyToMany(targetEntity="loic\ContentBundle\Entity\Content", mappedBy="filterfilter")
*/
private $contentcontent;
.....
/**
* Constructor
*/
public function __construct()
{
$this->contentcontent = new \Doctrine\Common\Collections\ArrayCollection();
$this->user = new \Doctrine\Common\Collections\ArrayCollection();
$this->status = 1;
}
......
/**
*
* @return the \Doctrine\Common\Collections\Collection
*/
public function getContentcontent() {
return $this->contentcontent;
}
/**
*
* @param
* $contentcontent
*/
public function setContentcontent($contentcontent) {
$this->contentcontent = $contentcontent;
return $this;
}
由于要检查 3 个过滤器,因此还需要 JOIN
3 次。就好像您有 3 个不同的 ManyToMany 关系并且只想要一行,这符合 3 个特定要求 - 唯一的区别是,您加入了相同的 table。未经测试,但它应该像这样工作
$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();
内部联接可能更好,因为您只需要满足这些要求的行。另请注意,使用过多的联接通常被认为是不好的做法,并且可能会降低性能。首选解决方案通常是构建特定视图而不是多个连接。
我在实体内容和过滤器之间存在多对多关系。 我想获得所有具有过滤器“1”、“2”和“3”(全部三个)的内容。我的查询给我的结果就像我会使用“或”一样,因为我得到的很多内容只有三个过滤器之一。
我的查询:
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;
}
}
实体过滤器:
use Doctrine\ORM\Mapping as ORM;
/**
* Filter
*
* * @ORM\Entity(repositoryClass="loic\FilterBundle\Entity\FilterRepository")
* @ORM\Table(name="filter", uniqueConstraints={@ORM\UniqueConstraint(name="idfilter_UNIQUE", columns={"idfilter"})}, indexes={@ORM\Index(name="fk_filter_filter_category1_idx", columns={"filter_category_idfilter_category"})})
*/
class Filter
{
/**
* @var integer
*
* @ORM\Column(name="idfilter", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $idfilter;
............
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\ManyToMany(targetEntity="loic\ContentBundle\Entity\Content", mappedBy="filterfilter")
*/
private $contentcontent;
.....
/**
* Constructor
*/
public function __construct()
{
$this->contentcontent = new \Doctrine\Common\Collections\ArrayCollection();
$this->user = new \Doctrine\Common\Collections\ArrayCollection();
$this->status = 1;
}
......
/**
*
* @return the \Doctrine\Common\Collections\Collection
*/
public function getContentcontent() {
return $this->contentcontent;
}
/**
*
* @param
* $contentcontent
*/
public function setContentcontent($contentcontent) {
$this->contentcontent = $contentcontent;
return $this;
}
由于要检查 3 个过滤器,因此还需要 JOIN
3 次。就好像您有 3 个不同的 ManyToMany 关系并且只想要一行,这符合 3 个特定要求 - 唯一的区别是,您加入了相同的 table。未经测试,但它应该像这样工作
$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();
内部联接可能更好,因为您只需要满足这些要求的行。另请注意,使用过多的联接通常被认为是不好的做法,并且可能会降低性能。首选解决方案通常是构建特定视图而不是多个连接。