2013-05-27 60 views
4

超过1000行的问题我有此查询将返回我在给定区域内的所有兴趣点:Doctrine2具有选择

$query = $em 
      ->createQuery(
        'SELECT f FROM MyApplication\MyBundle\Entity\POI p 
      WHERE (p.latitude BETWEEN :southEastLatitude AND :norhtWestLatitude) AND 
        (p.longitude BETWEEN :southEastLongitude AND :norhtWestLongitude) 
      ORDER BY p.name 
    '); 

    $query->setParameter(":norhtWestLatitude", $northWestLat); 
    $query->setParameter(":norhtWestLongitude", $northWestLng); 
    $query->setParameter(":southEastLatitude", $southEastLat); 
    $query->setParameter(":southEastLongitude", $southEastLng); 

如果我尝试用小面积访问(与小的差异PARAMS) ,我成功得到了结果。我想我得到的结果高达1000行......我不太确定。

如果我尝试用一​​个更大的区域来访问,我得到一个空结果...

不知怎的,射击与大面积的PARAMS相同的查询,我得到正确的结果集(〜1060行)。

所以我想了解一下学说的限制(甚至Symfony的???我用我的Symfony2项目里学说),还有什么?我也试过$query->setMaxResults(999999999);,但它并没有帮助...

任何人有同样的问题?

编辑:也许PHP的内存使用率是很高?我之前和调用getResult后添加这些行:

echo "Memory usage before: " . (memory_get_usage()/1024) . " KB" . PHP_EOL; 
echo "Memory usage after: " . (memory_get_usage()/1024) . " KB" . PHP_EOL; 

输出为:

内存使用后:5964.0625 KB

内存使用后:10019.421875 KB

编辑: 奇怪的测试:

1)如果我与这​​些参数进行测试:

WHERE 
    (f.latitude BETWEEN 45.64273082966722 AND 47.29965978937995) AND 
    (f.longitude BETWEEN 4.93262593696295 AND 9.99999999999999) 

我得到923行(正常行为)

2)如果我改变参数9.999999999999到10.000000000(或某些数目大于9.9999999 ),我在我的应用程序中得到一个空的结果集。 数据库仍返回923行(为10.000000000)。

编辑: 我能解决这个问题,这里讨论:https://groups.google.com/d/msg/doctrine-user/qLSon6m4nM4/y5vLztHcbDgJ

+1

app/logs/dev.log中的任何内容?检查PHP错误日志超过内存限制也许? – nifr

+0

可能是内存问题,并检查相关实体是否也被拉出。 – Geshan

+0

没有什么有趣的记录在app/logs/dev.log中,并且在php错误日志中没有记录。我没有收到任何错误消息,我只是得到一个空的结果集。 – eav

回答

2

从Doctrine2邮件列表中我得知你映射的属性类型“串”:

/** @ORM\Column(name="latitude", type="string", length=255, nullable=false) */ 
private $latitude; 

/** @ORM\Column(name="longitude", type="string", length=255, nullable=false) */ 
private $longitude; 

这意味着你的数据库将具有这些属性的VARCHAR列。所以当数据库运行你的查询时,它会执行一个字符串比较。

字符串比较不同于(正常)数字比较。见这些结果:

$a = 1234567890; 
$b = 987654321; 

echo $a == $b ? '0' : ($a < $b ? '-1' : '1'); // output: 1 (means $a is bigger than $b) 

echo strcmp($a, $b);       // output: -8 (means $a is smaller than $b) 

因此,这可能是最好的性质的东西将代表数字在你的数据库(十进制将是一个不错的选择)地图:

/** @ORM\Column(name="latitude", type="decimal", nullable=false) */ 
private $latitude; 

/** @ORM\Column(name="longitude", type="decimal", nullable=false) */ 
private $longitude; 

PS:你提到你得到有效的您自己执行查询时的结果。这可能是因为你做的事:

... latitude BETWEEN 45.64273082966722 AND 47.29965978937995 ... 

但原则(因为你映射属性字符串)就可以了:

... latitude BETWEEN '45.64273082966722' AND '47.29965978937995' ... 

注意这里的引号。这两个语句如何处理有很大的区别,比如我的测试用例演示;)

+0

绝对正确,可以理解。问题解决了。非常感谢(也在邮件列表中的帮助) – eav

1

它可能涉及到内存使用情况。请检查您的apache日志是否有内存错误。

当选择大量的数据,可能会有所帮助使用$query->iterate()代替$query->getResult()as pointed out in this article

要检查您的查询是否生成正确的SQL,您可以记录或以其他方式输出调用$query->getSQL()(设置参数后)的结果。将生成的SQL提供给您选择的数据库客户端,以查看是否返回了所需的结果。

+0

我没有收到内存耗尽错误,并且您发布的网站主要针对批量更改。我只选择 – eav

+1

本文的第二部分涉及选择大量项目,这将减少您的内存使用量。我用另一种故障排除方法扩展了我的答案(检查SQL)。 – chiborg