Php 优化条令查询以防止附加查询
我正在构建一个有更新墙的系统,在这里你只能看到朋友的帖子。 这里的“朋友”由两个用户组成,每个用户都将彼此添加到他们的朋友列表中 朋友关系的处理非常简单,只需一个条令Php 优化条令查询以防止附加查询,php,mysql,symfony,doctrine-orm,doctrine,Php,Mysql,Symfony,Doctrine Orm,Doctrine,我正在构建一个有更新墙的系统,在这里你只能看到朋友的帖子。 这里的“朋友”由两个用户组成,每个用户都将彼此添加到他们的朋友列表中 朋友关系的处理非常简单,只需一个条令manytomy关系,如下所示: User.php //.. other declarations /** * @var ArrayCollection * @ORM\ManyToMany(targetEntity="User") * @ORM\JoinTable(name="user_friends") */ protec
manytomy
关系,如下所示:
User.php
//.. other declarations
/**
* @var ArrayCollection
* @ORM\ManyToMany(targetEntity="User")
* @ORM\JoinTable(name="user_friends")
*/
protected $friends;
//.. more unrelated stuff
并在我的查询中获得用户朋友的更新(包括他们自己)
UpdateRepository.php
/**
* Get aggregated list of updates for a user and their friends in chronological order
* @param User $user
* @return array
*/
public function getWallUpdates(User $user)
{
$qb = $this->getEntityManager()->createQueryBuilder('p');
$qb->select(['p'])->from($this->getEntityName(), 'p');
$criteria = $qb->expr()->andX();
// Filter based on Friends
$friends = [$user];
foreach($user->getFriends() as $friend) // collect eligible friends
if($friend->getFriends()->contains($user))
$friends[] = $friend;
$criteria->add('p.account IN (:friends)');
$qb->setParameter('friends', $friends);
// Filter based on Chronology
// Filter based on Privacy
$criteria->add('p.privacy IN (:privacy)');
$qb->setParameter('privacy', [1, 3]);
$qb->where($criteria);
$query = $qb->getQuery();
$result = $query->getResult();
return $result;
}
现在这个可以运行了,但问题是,如果($friend->getFriends()->包含($user))
行需要知道另一个用户的朋友列表中是否存在$user
,它会为$user
的朋友列表中的每个人生成一个新的查询
我不介意用一两个额外的查询来完成这个任务,但我需要在这里讨论一下规模。此应用程序上的一个人可能有数百个朋友。我无法在每次加载此页面时执行数百个查询(尽管它们可能很小),这可能会非常多
让这一切变得更好的最佳解决方案是什么
现在我可以继续开发,因为它确实正常工作
编辑
为了简洁起见,我确实尝试过使用EXTRA\u LAZY
方法,在我的用户实体中向$friends manytomy声明添加EXTRA\u LAZY
。根据文档,如果使用EXTRA_LAZY
fetch模式,使用Collection#contains(entity)
不会触发查询
显然,这里的问题源于这样一个事实,$user
s的朋友都需要收集他们的朋友列表以便进行检查。这对我来说很有意义
还有一种方法可以将这一切合并到一个操作中吗?如果在获取$user对象时为用户的朋友和他们的朋友添加连接,那么它应该可以删除任何延迟加载。例如,您可以为用户创建一个自定义存储库,如下所示:
use Doctrine\ORM\EntityRepository;
class UserRepository extends EntityRepository {
public function fetchFriendsOfFriends($userId) {
return $this->_em->createQuery('SELECT u, f, ff FROM User u '
. 'LEFT JOIN u.friends f '
. 'LEFT JOIN f.friends ff '
. 'WHERE u.id = :userId')
->setParameter('userId', $userId)
->getSingleResult();
}
}
获取您的用户实体以使用此存储库:
/**
* @ORM\Entity(repositoryClass="UserRepository")
*/
class User {
...
然后,在获取$user时,使用新的获取方法:
$user = $em->getRepository('User')->fetchFriendsOfFriends($userId);
我还没有对它进行测试,但我认为它会减少延迟加载的需要