这个问题的关键在于弄清楚哪种技术更好,并听取了一些熟练的symfony2程序员的不同意见。
一个例子将说明挑战和“挑战评级”表,许多人可以对某些挑战进行评级。 (类似于stackoverflow投票问题系统)。
表格如下所示:(like_dislike是boolean(1 = like,0 = dislike)
数据量将为10-200 +挑战率。
挑战实体
/**
* Challanges
*
* @ORM\Table(name="challanges")
* @ORM\Entity(repositoryClass="TB\ChallangesBundle\Entity\ChallangesRepository")
*/
class Challanges
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
* @Assert\NotBlank()
*/
private $name;
/**
* @var string
*
* @ORM\Column(name="slug", type="string", length=255, unique=true)
*/
private $slug;
/**
* @var string
*
* @ORM\Column(name="description", type="text")
* @Assert\NotBlank()
*/
private $description;
/**
* @var \DateTime
* @ORM\Column(name="start_date", type="datetime", nullable=false)
* @Assert\DateTime()
*/
private $start_date;
/**
* @var \DateTime
* @ORM\Column(name="end_date", type="datetime", nullable=false)
* @Assert\DateTime()
*/
private $end_date;
/**
* @ORM\ManyToOne(targetEntity="TB\UserBundle\Entity\User", fetch="EXTRA_LAZY")
* @ORM\JoinColumn(name="owner_id", referencedColumnName="id", nullable=false)
*/
protected $owner;
/**
* @ORM\OneToMany(targetEntity="TB\ChallangesBundle\Entity\ChallangeRating", mappedBy="challange", cascade={"persist", "remove"})
*/
protected $likes;
/**
* Constructor
*/
public function __construct()
{
$this->likes = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add likes
*
* @param \TB\ChallangesBundle\Entity\ChallangeRating $likes
* @return Challanges
*/
public function addLike(\TB\ChallangesBundle\Entity\ChallangeRating $likes)
{
$this->likes[] = $likes;
return $this;
}
/**
* Remove likes
*
* @param \TB\ChallangesBundle\Entity\ChallangeRating $likes
*/
public function removeLike(\TB\ChallangesBundle\Entity\ChallangeRating $likes)
{
$this->likes->removeElement($likes);
}
/**
* Get likes
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getLikes()
{
return $this->likes;
}
public function filterLikesInChallenge($like_dislike) {
$criteria = Criteria::create();
$criteria->where(Criteria::expr()->eq('like_dislike', $like_dislike));
return $this->likes->matching($criteria);
}
public function checkIfUserRatedAlready(\TB\UserBundle\Entity\User $user)
{
$criteria = Criteria::create();
$criteria->where(Criteria::expr()->eq('fan', $user));
return $this->likes->matching($criteria);
}
挑战评级实体
<?php
namespace TB\ChallangesBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* ChallangeRating
*
* @ORM\Table(name="challange_rating")
* @ORM\Entity(repositoryClass="TB\ChallangesBundle\Entity\ChallangeRatingRepository")
*/
class ChallangeRating
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var boolean
*
* @ORM\Column(name="like_dislike", type="boolean")
*/
private $like_dislike;
/**
* @ORM\ManyToOne(targetEntity="TB\UserBundle\Entity\User", inversedBy="fans")
*/
protected $fan;
/**
* @ORM\ManyToOne(targetEntity="TB\ChallangesBundle\Entity\Challanges", inversedBy="likes")
*/
protected $challange;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Get like_dislike
*
* @return boolean
*/
public function getLikeDislike()
{
return $this->like_dislike;
}
/**
* Set like_dislike
*
* @param boolean $like_dislike
* @return ChallangeRating
*/
public function setLikeDislike($like_dislike)
{
$this->like_dislike = $like_dislike;
return $this;
}
/**
* Set fan
*
* @param \TB\UserBundle\Entity\User $fan
* @return ChallangeRating
*/
public function setFan(\TB\UserBundle\Entity\User $fan = null)
{
$this->fan = $fan;
return $this;
}
/**
* Get fan
*
* @return \TB\UserBundle\Entity\User
*/
public function getFan()
{
return $this->fan;
}
/**
* Set challange
*
* @param \TB\ChallangesBundle\Entity\Challanges $challange
* @return ChallangeRating
*/
public function setChallange(\TB\ChallangesBundle\Entity\Challanges $challange = null)
{
$this->challange = $challange;
return $this;
}
/**
* Get challange
*
* @return \TB\ChallangesBundle\Entity\Challanges
*/
public function getChallange()
{
return $this->challange;
}
}
好的,现在我想:
控制器
获得$ challenge的经典开始
// this will take care of point number 1 (display challenge details) (1.)
$challange = $challangesRepo->findOneBy(array('slug'=>$slug));
// display numbers of likes and dislikes for certain challenge (2.)
但现在是一个决定......
我应该通过从querybuilder查询数据库获得喜欢的吗? (经典选择计数)
或
我应该使用这样的集合和标准吗? :
$challangeLikes = $challange->filterLikesInChallenge(1);
$challangeDislikes = $challange->filterLikesInChallenge(0);
**内存使用效果更好? DB表现更好的是什么? **
如果我没有错,则以下两个方法执行以下两个查询:
SELECT
t0.id AS id1,
t0.like_dislike AS like_dislike2,
t0.fan_id AS fan_id3,
t0.challange_id AS challange_id4
FROM
challange_rating t0
WHERE
(
t0.like_dislike = ? AND t0.challange_id = ?
)
Parameters: [1, 12]
SELECT
t0.id AS id1,
t0.like_dislike AS like_dislike2,
t0.fan_id AS fan_id3,
t0.challange_id AS challange_id4
FROM
challange_rating t0
WHERE
(
t0.like_dislike = ? AND t0.challange_id = ?
)
现在我可以将喜欢,不喜欢的数量传递给以下视图:
'challangeLikes'=>$challangeLikes->count(),
'challangeDislikes'=>$challangeDislikes->count(),
如果我想知道某位用户是否已经对此挑战进行了评分,该怎么办?
再次......
*我应该使用经典的querybuilder样式和select count *
或
我应该使用像这样的方法:
$ratedAlreadyCol = $challange->checkIfUserRatedAlready($user)->first();
那会实际执行另一个查询吗?像经典选择计数的东西,但该集合将为我做这个?所以这不是在一些大型内存阵列中搜索allll喜欢但是它是对DB的查询?
SELECT
t0.id AS id1,
t0.like_dislike AS like_dislike2,
t0.fan_id AS fan_id3,
t0.challange_id AS challange_id4
FROM
challange_rating t0
WHERE
(
t0.fan_id = ? AND t0.challange_id = ?
)
Parameters: [25, 12]
我想展示所有“粉丝 - 评定某项挑战的人”......
...再次
我应该在存储库中创建一个单独的querybuilder方法,选择针对某些挑战的所有评级,并使用内部联接到users表(这样我可以显示个人资料图像和用户名)
或
我是否应该获得所有评级,并在其中通过它来完成:
$challangeLikesCollection = $challange->getLikes();
{% for bla bla
如果我这样做的话......教义会对循环中的每个“粉丝”执行一个针对用户表的选择查询...当有人说... 200粉丝......那不是好吧?
能以某种方式请他提供处理这些情况的方法吗?有什么建议?
或者您使用其他任何技术?
我非常关心内存使用和数据库加载时间,因为它将在任何地方使用,每个用户都会有这样一个列出不同挑战的列表。该列表将包括让我们说15个挑战,并将所有喜欢,不喜欢的内容连接到列表中的每个挑战等等......表演......
感谢您的解释,提示和提示,以帮助我和其他读者在另一个层面上移动!
答案 0 :(得分:0)
我会做以下事情:
稍微规范化并将number of likes
和number of dislikes
字段添加到Challenge
,并在addLike
和removeLike
将like_dislike
重命名为like
,因为它是布尔字段,1表示0表示不喜欢
使用单独的查询查询用户列表并使用数组水化和INDEXBY用户名(它必须是唯一的或用户ID)或者可以创建自定义水分器
SELECT u.username,u.photo FROM User u INNER JOIN u.ratings WITH r.fan =:fan INDEX BY u.username
或类似的东西。您可以检查当前用户的用户名是否在阵列中。
我认为这可能足够高效。
一些解释:
INDEX BY means结果集合或数组键(索引)将是字段的值(此字段必须是唯一的)。当您使用INDEX BY时,结果集将包含已知的键,因此您可以直接在恒定时间内(并且不必搜索整个结果集)到达(例如检查是否存在)单个结果。
Doctrine在下面使用PDO,水化意味着如何处理PDO结果集并将其转换为其他内容。默认对象水合意味着结果集将被转换为对象图,这是一个非常昂贵的操作。有other hydration modes便宜,但你松散了一些灵活性。例如。如果你使用数组水合,结果将是一个数组数组,所以你不能修改它(我的意思是坚持回数据库)所以它只是为了阅读而结果不是实体对象你不能使用它的方法,例如定制的吸气剂。如果需要,您可以创建custom hydrators。