我有一个用户实体和一个Event实体。用户可以通知他们想要参加某些活动。 这些用户也有自己的朋友(自我引用多对多关系)。
我希望从我的数据库中检索用户'满足以下条件的朋友: 他们想参加同一场比赛。 他们彼此相邻。
虽然第二个条件没问题,但我尝试建立最佳查询以确保第一个条件得到尊重。
这是我到目前为止所做的:
$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' ) );
对我来说不幸的是,这不是我想做的事情。我想知道为什么。 因此,一旦我选择了朋友,我基本上只想选择那些已经通知他们想要参加同样事件的朋友。
因此,我正在做一个内部加入,以检查朋友(他们也是用户)是否已通知他们想要参加活动。然后在那些朋友中,我想只选择那些与我$qb->expr()->eq('FRIENDS.eventNotified.id', 'USER.eventNotified.id')
发生同样事件的人。
我认为存在我的问题...因为eventNotified是EVENT实体的集合,我希望仅选择我们已经通知的事件,我可以摆脱.id
吗?另外,我觉得这只是在我想要检索我们在commun中发生的事件时选择所有事件。所以我相信我应该在某处做一个内心加入,但我能找到合适的合成器。
有什么建议吗?
由于
奖金:我是否还应该指定我想要检索' c'和' p'在SELECT语句中?
编辑:
我尝试了下面的解决方案,但是我收到了这个错误,我不明白。如何检索完整的错误消息? (有些部分遗失!)
我尝试过的代码:
//我们只想返回附近可用的用户或谁 $ 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 FRIENDS WITH 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(686): Doctrine \ ORM \ Query \ Parser-> semanticalError(' Invalid PathExp ...', 阵列)#2 /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/Parser.php(240): 教义\ ORM \查询\ Parser-> _processDeferredPathExpressions(对象(学说\ ORM \查询\ AST \ SelectStatement))#3 /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/Parser.php(304): Doctrine \ ORM \ Query \ Parser-> getAST()#4 /用户 /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'不是......', 阵列)#2 /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/Parser.php(233): 教义\ ORM \查询\ 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;
答案 0 :(得分:1)
一些想法:
您可以尝试使用$qb->expr()->eq('FRIENDS.eventNotified', 'USER.eventNotified')
而不是$qb->expr()->eq('FRIENDS.eventNotified.id', 'USER.eventNotified.id')
之类的内容,因为我认为eventNotified是一个与用户相关的实体,您的USER实体中的属性名称是eventNotified。
无论如何,我会在联接中直接使用“with”,因此您可以独立于where子句限制联接结果:
->leftJoin('USER.friends', 'FRIENDS', 'WITH', 'FRIENDS.eventNotified = USER.eventNotified') // I'm going to take all of his friends
Bonus:我还应该指定我想在SELECT语句中检索'c'和'p'吗? 答:是的,如果你想在没有对数据库的新查询之后用你的getter检索它们