4

指定されたエリアのすべての POI を返す次のクエリがあります。

    $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);

小さい領域(パラメータの差が小さい)でアクセスしようとすると、うまく結果が得られます。1000行までの結果が得られると思います...よくわかりません。

より大きな領域でアクセスしようとすると、空の結果セットが得られます...

どういうわけか、より大きな領域のパラメーターを使用して同じクエリを実行すると、正しい結果セット (〜 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

4

2 に答える 2

2

From the Doctrine2 mailing list I learned that you mapped the properties as type "string":

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

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

This means that your db will have VARCHAR columns for these properties. So when the db runs your query, it will perform a string-compare.

A string-compare is different from a (normal) number-compare. See these results:

$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)

So it's probably best to map the properties as something that represents numbers in your db (DECIMAL would be a good choice):

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

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

PS: You mention you get valid results when you perform the query yourself. This is probably because you did:

... latitude BETWEEN 45.64273082966722 AND 47.29965978937995 ...

But Doctrine (because you mapped the properties as strings) will do:

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

Note the quotes here. There is a big difference in how these two statements are treated, like my test-case shows ;)

于 2013-05-29T20:03:24.393 に答える