【发布时间】:2014-03-08 18:07:49
【问题描述】:
我有一个用户实体和一个事件实体。用户可以通知他们想参加一些活动。 这些用户也有自己是用户的朋友(自引用多对多关系)。
我希望从我的数据库中检索满足以下条件的用户朋友: 他们想参加同一个活动。 它们彼此靠近。
虽然第二个条件很好,但我正在尝试构建可能的最佳查询,以确保遵守第一个条件。
这是我到目前为止所做的:
$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' ) );
对我来说不幸的是,这不是我想做的事情。我想知道为什么。 因此,一旦我选择了 FRIENDS,我基本上只想选择那些通知他们想参加与我通知的活动相同的活动的朋友。
所以我正在做一个 innerJoin 来检查朋友(他们也是用户)是否通知他们想要参加活动。然后在那些朋友中,我只想选择那些与我$qb->expr()->eq('FRIENDS.eventNotified.id', 'USER.eventNotified.id')参加相同活动的人。
我认为这是我的问题......因为 eventNotified 是 EVENT 实体的集合,我希望只选择我们都通知的事件,我可以摆脱 .id 吗?另外,当我只想检索我们在社区中通知的事件时,我感觉这是在选择所有事件。所以我相信我应该在这里的某个地方做一个 innerJoin 但我可以找到正确的合成器。
有什么建议吗?
谢谢
奖励:我是否还应该在 SELECT 语句中指定要检索“c”和“p”?
编辑:
我尝试了以下解决方案,但我收到了这个我不明白的错误。如何检索完整的错误消息? (有些部分不见了!)
我尝试过的代码:
//我们只想返回附近有空的用户或者谁 $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 = :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();
错误:
致命错误:未捕获的异常 'Doctrine\ORM\Query\QueryException' 带有消息'SELECT USER,FRIENDS FROM Entity\User USER LEFT JOIN USER.friends 与 USER.eventNotified 的朋友 = FRIENDS.eventNotified WHERE USER = :user' 在 /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/QueryException.php:39Stack 跟踪:#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...', 数组)#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 第 49 行
Doctrine2 似乎出于某种原因不喜欢'WITH', 'USER.eventNotified = FRIENDS.eventNotified'。我真的不明白为什么。没有这段代码,代码可以正常工作,但这个条件确实不满足。
非常感谢您的帮助
EDIT2:
在尝试了以下答案的第三条评论中的内容后,我仍然收到类似的错误消息:
致命错误:未捕获的异常 'Doctrine\ORM\Query\QueryException' 带有消息 'SELECT USER, FRIENDS, EVENT, c, p FROM Entity\User USER LEFT JOIN USER.friends FRIENDS WHERE USER = :user AND USER.eventNotified = FRIENDS.eventNotified' 在 /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/QueryException.php:39Stack 跟踪:#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 ...', 数组)#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 在 /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/QueryException.php 第 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;
【问题讨论】:
-
您的结果有什么问题?也许对朋友使用 innerJoin?
-
我不知道把innerjoin放在朋友的哪里。我没有检索到正确的结果集..
-
也许把这个
->leftJoin('USER.friends', 'FRIENDS')改成->innerJoin('USER.friends', 'FRIENDS')? -
hmm 不,因为它只会选择有朋友的用户,但每个用户都有朋友,我已经指定了哪里 User.id = userid
-
这是有道理的。那么您是否获得了根本不匹配的用户,或者您是否获得了重复的结果?也可以发布架构的相关部分。这可能对其他人有帮助。
标签: symfony join doctrine-orm inner-join query-builder