2014-02-11 23 views
0

我有一个用户实体和一个事件实体。用户可以通知他们想要参加一些活动。 这些用户也有自己的用户(自引用多对多关系)的朋友。何时使用innerJoin而不是使用Doctrine 2的地方?

我正在寻找从我的数据库中检索满足以下条件的用户朋友: 他们想要参加同一个活动。 他们彼此相邻。

虽然第二个条件很好,但我试图建立最佳查询,以确保第一个条件得到尊重。

这是我迄今所做的:不幸的是,我

$qb = $this->getEntityManager()->createQueryBuilder(); 


     $qb->select('USER', 'FRIENDS') // Selecting Me, the user who is asking to retrieve the users matched, and the friends who fill the criterias below 
      ->from('Entity\User', 'USER') // we start with the user 
      ->where('USER.id = :userId') // And I want the user the be me 
      ->leftJoin('USER.friends', 'FRIENDS') // I'm going to take all of his friends 
      ->innerJoin('FRIENDS.eventNotified', 'EVENT') //but ONLY the ones that have notified Events (array collection ov EVENT entity) 
      ->leftJoin('EVENT.categories', 'c') //take events category in order to avoid doing any request when getting the name of the category 
      ->leftJoin('EVENT.place', 'p') // same with the place where the event occured 
      ->andWhere( 
       $qb->expr()->andX(
        $qb->expr()->between('FRIENDS.latitude', ':minLat', ':maxLat'), //in a defined area 
        $qb->expr()->between('FRIENDS.longitude', ':minLng', ':maxLng'), 
        $qb->expr()->eq('FRIENDS.eventNotified.id', 'USER.eventNotified.id') //I want to select ONLY the friends who have notified they want to go to the same events than me (I have notified the same events as well) 
       ) 
      ) 
      ->add('orderBy', $qb->expr()->sum('FRIENDS.latitude - :lat', 'FRIENDS.longitude - :lng')); 

,这不是在做什么,我期待的事情。我想知道为什么。 因此,一旦我选择了朋友,我基本上只想选择已通知他们想要参加与我已通知的相同活动的朋友。

因此,我正在做一个innerJoin来检查朋友(他们是否是用户)已通知他们想要参加活动。然后在这些朋友中,我只想选择与我的$qb->expr()->eq('FRIENDS.eventNotified.id', 'USER.eventNotified.id')相同的事件。

我认为这是我的问题...因为eventNotified是EVENT实体的集合,我只希望选择我们都通知的事件,我可以摆脱.id?另外,我感觉这是选择所有的事件,当我只想检索我们在共同通知的事件时。所以我相信我应该在这里做一个内心的加入,但我可以找到合适的合成器。

有什么建议吗?

感谢

奖励:我应该还可以指定我想找回在SELECT语句中的“C”和“P”?

编辑:

我尝试了以下解决方案,但我得到这个错误,我不明白。我如何检索完整的错误信息? (部分缺失!)

码我曾尝试:

//我们只想要回附近的用户谁是可用的或者谁 $ QB = $这个 - > getEntityManager() - > createQueryBuilder() ;

$qb->select('USER', 'FRIENDS') // Selecting Me, the user who is asking to retrieve the users matched, and the friends who fill the criterias below 
     ->from('Entity\User', 'USER') // we start with the user 
     ->where('USER = :user') // And I want the user the be me 
     ->leftJoin('USER.friends', 'FRIENDS', 'WITH', 'USER.eventNotified = FRIENDS.eventNotified'); 

    $array = array(
     'user' => $user 
    ); 

    $qb->setParameters($array); 

    $usersMatched = $qb->getQuery()->getResult(); 

错误:

Fatal error: Uncaught exception 'Doctrine\ORM\Query\QueryException' with message 'SELECT USER, FRIENDS FROM Entity\User USER LEFT JOIN USER.friends FRIENDS WITH USER.eventNotified = FRIENDS.eventNotified WHERE USER = :user' in /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/QueryException.php:39Stack trace:#0 /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/Parser.php(429): Doctrine\ORM\Query\QueryException::dqlError('SELECT USER, FR...')#1 /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/Parser.php(686): Doctrine\ORM\Query\Parser->semanticalError('Invalid PathExp...', Array)#2 /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/Parser.php(240): Doctrine\ORM\Query\Parser->_processDeferredPathExpressions(Object(Doctrine\ORM\Query\AST\SelectStatement))#3 /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/Parser.php(304): Doctrine\ORM\Query\Parser->getAST()#4 /Users in /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/QueryException.php on line 49

看来,Doctrine2不喜欢'WITH', 'USER.eventNotified = FRIENDS.eventNotified'出于某种原因。我不明白为什么。没有这一点代码,代码工作正常,但这种情况确实没有实现。

非常感谢您的帮助

EDIT2:

想什么在下面的答案的第三点意见,我仍然得到类似的错误消息后:

Fatal error: Uncaught exception 'Doctrine\ORM\Query\QueryException' with message 'SELECT USER, FRIENDS, EVENT, c, p FROM Entity\User USER LEFT JOIN USER.friends FRIENDS WHERE USER = :user AND USER.eventNotified = FRIENDS.eventNotified' in /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/QueryException.php:39Stack trace:#0 /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/Parser.php(429): Doctrine\ORM\Query\QueryException::dqlError('SELECT USER, FR...')#1 /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/Parser.php(528): Doctrine\ORM\Query\Parser->semanticalError(''EVENT' is not ...', Array)#2 /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/Parser.php(233): Doctrine\ORM\Query\Parser->_processDeferredIdentificationVariables()#3 /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/Parser.php(304): Doctrine\ORM\Query\Parser->getAST()#4 /Users/YohannM/Sites/meetmyfrien in /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/QueryException.php on line 49

我想我们不能做动态条件。我不知道是否有一种方法与原则去做,否则我可能不得不这样做用PHP我想..

这里是我的事件和用户实体的结构:

用户实体:

class User { 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer", nullable=false, unique=true) 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="IDENTITY") 
    */ 
    private $id; 

    /** 
    * @var integer 
    * 
    * @ORM\Column(name="fb_id", type="bigint", nullable=false, unique=true) 
    */ 
    private $fb_id; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="firstname", type="string", length=100, nullable=false, unique=false) 
    */ 
    private $first_name; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="lastname", type="string", length=100, nullable=true, unique=false) 
    */ 
    private $last_name; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="email", type="string", length=255, nullable=true, unique=true) 
    */ 
    private $email; 

    /** 
    * @var integer 
    * 
    * @ORM\Column(name="notation", type="integer", nullable=true, unique=true) 
    */ 
    private $notation; 

    /** 
    * Bidirectional - Many users have Many favorite comments (OWNING SIDE) 
    * 
    * @var \Doctrine\Common\Collections\Collection 
    * 
    * @ORM\ManyToMany(targetEntity="Entity\Category", inversedBy="userInterests") 
    */ 
    private $interests; 

    /** 
    * @var \Doctrine\Common\Collections\Collection 
    * 
    * @ORM\ManyToMany(targetEntity="Entity\User", cascade={"persist"}) 
    * @ORM\JoinTable(name="friends", 
    *  joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")}, 
    *  inverseJoinColumns={@ORM\JoinColumn(name="friend_user_id", referencedColumnName="id")} 
    *  ) 
    **/ 
    private $friends; 

    /** 
    * @var \Doctrine\Common\Collections\Collection 
    * 
    * @ORM\OneToMany(targetEntity="Entity\Request", mappedBy="user", cascade={"remove"}, orphanRemoval=true) 
    * @ORM\JoinColumn(nullable=true) 
    */ 
    private $requests; 

    /** 
    * @var \Doctrine\Common\Collections\Collection 
    * 
    * @ORM\OneToMany(targetEntity="Entity\Request", mappedBy="friend", cascade={"remove"}, orphanRemoval=true) 
    * @ORM\JoinColumn(nullable=true) 
    */ 
    private $notifications; 

    /** 
    * Bidirectional - Many users have notified they want to go to different events (OWNING SIDE) 
    * 
    * @var \Doctrine\Common\Collections\Collection 
    * 
    * @ORM\ManyToMany(targetEntity="Entity\Event", inversedBy="userNotified", cascade={"persist"}) 
    */ 
    private $eventNotified; 

    /** 
    * @var integer 
    * 
    * @ORM\Column(name="age", type="integer", length=3, nullable=true, unique=false) 
    */ 
    private $age; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="description", type="text", nullable=true, unique=false) 
    */ 
    private $description; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="picture", type="string", length=300, nullable=true, unique=false) 
    */ 
    private $picture; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="genre", type="string", length=10, nullable=true, unique=false) 
    */ 
    private $genre; 

    /** 
    * @var boolean 
    * 
    * @ORM\Column(name="isregistered", type="boolean", length=1, nullable=false, unique=false) 
    */ 
    private $registered; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="latitude", type="decimal", length=64, precision=25, scale=20, nullable=true, unique=false) 
    */ 
    private $latitude; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="longitude", type="decimal", length=64, precision=25, scale=20, nullable=true, unique=false) 
    */ 
    private $longitude; 

    /** 
    * @var \Entity\Security_Key 
    * 
    * @ORM\OneToOne(targetEntity="Entity\Security_Key", cascade={"persist","remove"}, orphanRemoval=true) 
    * @ORM\JoinColumns({ 
    * @ORM\JoinColumn(name="private_key_id", referencedColumnName="id", unique=true, onDelete="SET NULL") 
    * }) 
    */ 
    private $private_key; 

    /** 
    * @var boolean 
    * 
    * @ORM\Column(name="isavailable", type="boolean", length=1, nullable=false, unique=false) 
    */ 
    private $available = 0; 

事件实体:

class Event 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer", precision=0, scale=0, nullable=false, unique=false) 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="IDENTITY") 
    */ 
    private $id; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="name", type="string", length=200, precision=0, scale=0, nullable=false, unique=false) 
    */ 
    private $name; 

    /** 
    * @var \Doctrine\Common\Collections\Collection 
    * 
    * @ORM\ManyToMany(targetEntity="Entity\Category", inversedBy="events") 
    * @ORM\JoinTable(name="categories_events") 
    */ 
    private $categories; 


    /** 
    * @var \Entity\User 
    * 
    * @ORM\ManyToOne(targetEntity="Entity\User", inversedBy="events") 
    * @ORM\JoinColumn(name="user_id", referencedColumnName="id") 
    **/ 
    private $user; 


    /** 
    * @var \Entity\Admin 
    * 
    * @ORM\ManyToOne(targetEntity="Entity\Admin", inversedBy="events") 
    * @ORM\JoinColumn(name="admin_id", referencedColumnName="id") 
    **/ 
    private $admin; 

    /** 
    * @var \Entity\Place 
    * 
    * @ORM\ManyToOne(targetEntity="Entity\Place", inversedBy="events", cascade={"persist"}) 
    * @ORM\JoinColumn(nullable=false) 
    */ 
    private $place; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="description", type="text", precision=0, scale=0, nullable=true, unique=false) 
    */ 
    private $description; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="link", type="string", length=200, nullable=true, unique=false) 
    */ 
    private $link; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="picture", type="string", length=100, precision=0, scale=0, nullable=true, unique=false) 
    */ 
    private $picture; 

    /** 
    * @var \DateTime 
    * 
    * @ORM\Column(name="date_created", type="datetime", precision=0, scale=0, nullable=false, unique=false) 
    */ 
    private $dateCreated; 

    /** 
    * @var \DateTime 
    * 
    * @ORM\Column(name="date_start", type="datetime", precision=0, scale=0, nullable=true, unique=false) 
    */ 
    private $dateStart; 

    /** 
    * @var \DateTime 
    * 
    * @ORM\Column(name="date_end", type="datetime", precision=0, scale=0, nullable=true, unique=false) 
    */ 
    private $dateEnd; 

    /** 
    * @var boolean 
    * 
    * @ORM\Column(name="confirmed", type="boolean", length=1, nullable=false, unique=false) 
    */ 
    private $confirmed; 

    /** 
    * Bidirectional - One-To-Many (INVERSE SIDE) 
    * 
    * @var \Doctrine\Common\Collections\Collection 
    * 
    * @ORM\OneToMany(targetEntity="Entity\Request", mappedBy="event") 
    */ 
    private $invitations; 

    /** 
    * Bidirectional - Many users are intending many events (INVERSE SIDE) 
    * 
    * @ORM\ManyToMany(targetEntity="User", mappedBy="eventNotified", cascade={"persist"}) 
    */ 
    private $userNotified; 
+0

你的结果出了什么问题?也许使用innerJoin对朋友? – Gohn67

+0

我不知道把innerjoin放在朋友的哪里。我没有检索到正确的结果集。 –

+0

也许可以将''> leftJoin('USER.friends','FRIENDS')'改为' - > innerJoin('USER.friends','FRIENDS')'? – Gohn67

回答

1

几个想法:

你可以尝试使用类似$qb->expr()->eq('FRIENDS.eventNotified', 'USER.eventNotified')而不是$qb->expr()->eq('FRIENDS.eventNotified.id', 'USER.eventNotified.id'),因为我认为eventNotified是某种与用户相关的实体,其中USER实体中的属性名称是eventNotified。

无论如何,我会直接使用“与”的加入,让你单独限制你的where子句中的连接结果:

->leftJoin('USER.friends', 'FRIENDS', 'WITH', 'FRIENDS.eventNotified = USER.eventNotified') // I'm going to take all of his friends 

奖励:我应该还可以指定我想找回“C”和'p'在SELECT语句中? 答案:是的,如果你想在没有对数据库的新查询之后用你的获得者检索它们

+0

非常有帮助,让我试试这个:) –

+0

我试过你的解决方案,这似乎是我需要的,但我无法绕过错误消息你看我的编辑.. –

+1

它可能无法与动态“与”(不固定值)或与自引用关联,我不能确定没有测试它或进行更深入的研究。你可以试试这个,如果你有一些错误,在这里写你的Apache日志/你的例外? ('USER ='user') - > leftJoin('USER','FRIENDS') - > from('Entity \ User','USER') - 'USER.friends','朋友') - >和Where('USER.eventNotified = FRIENDS.eventNotified')' 您是否还可以编写实体的基础知识?也就是说,受影响的属性:eventNotified,朋友... – jdharandas

相关问题