PHP, запрос Mongo с использованием или и точечной нотации

У меня проблема, которая сводит меня с ума!

Мне нужно перевести следующий запрос Mongo в PHP:

db.mycollection.find({$or: [ {'field.a': 45.4689, 'field.b': 9.18103}, {'field.a' : 40.71455, 'field.b': -74.007124} ]})

Он отлично работает из оболочки.

Я думаю, что запрос должен быть переведен на PHP следующим образом (var_dump):

Array
    (
        [$or] => Array
            (
                [0] => Array
                    (
                        [field.a] => 45.468945
                        [field.b] => 9.18103
                    )

                [1] => Array
                    (
                        [field.a] => 40.71455
                        [field.b] => -74.007124
                    )

            )

    )

но я не получаю результатов в PHP!

Почему? Что случилось? Какой правильный синтаксис?

Благодарю вас!


person upanisad    schedule 30.04.2012    source источник
comment
Как вы можете говорить, что это не работает с PHP? Возможно, вы написали какой-то PHP-код, который создает не тот же самый запрос, а что-то другое? Пожалуйста, предоставьте доказательство того, что вы делаете этот запрос в PHP, например. поделившись своим PHP-кодом и поделившись сгенерированной строкой запроса. - Запрос, которым вы делитесь, представляет собой массив, а не строку, как в оболочке.   -  person hakre    schedule 30.04.2012


Ответы (1)


Ваш синтаксис кажется мне хорошим, я думаю, что основная проблема заключается в том, что вы используете числа с плавающей запятой, которые не всегда так точны, как вы думаете, особенно если вы сами перепутали 45,4689 и 45,468945. Для прямого сравнения чисел с плавающей запятой всегда следует добавлять небольшой коэффициент фаззинга.

В этом случае вы, кажется, используете координаты? Если это так, я предлагаю вам:

  • поменять местами поля a и b (чтобы вы получили долготу, а затем широту)
  • создать двухмерный индекс для «поля»: sureIndex(array('field' => '2d'));
  • используйте geoNear с небольшим максимальным расстоянием и ограничением 1,

Это должно дать гораздо лучший способ сканирования точек. Однако вам придется выполнить запрос дважды, так как команда geoNear не может выполнить $or.

Если у вас есть только дискретный набор точек (как, кажется, указывают ваши комментарии), я бы рекомендовал не запрашивать числа с плавающей запятой, а просто добавить поле с названием города.

person Derick    schedule 30.04.2012
comment
Привет, Дерик, ты прав! Да, это координаты, и я пытался сделать то, что вы догадались. Вы были правы, проблема в точности... Дело в том, что запрос должен работать так: Получить первые 10 результатов, которые. например, расположены в Нью-Йорке или Милане, упорядоченные по другому полю, и я имею в виду всего 10, Нью-Йорк + Милан (таким образом, 1-й результат может быть Нью-Йорк, 2-й Милан, 3-й, 4-й снова Нью-Йорк и так далее). Общее количество документов огромно, мне нужно всего 10 вместе взятых. Поэтому я не могу использовать пространственные запросы и не могу агрегировать результаты на уровне приложения. Так что, это просто невозможно сделать? :/ - person upanisad; 30.04.2012