Пример использования геопространственной индексации с pymongo - PullRequest
1 голос
/ 07 апреля 2020

Я рассматривал использование MongoDB вместо пользовательской геопространственной базы данных, однако мне трудно понять, как pymon go работает со сферическими координатами. В частности, я не уверен, что $ maxDistance (и подобные имеют какой-либо эффект). Например, если я выполню этот код:

db = pymongo.MongoClient().geo_example
db.places.create_index([("location", pymongo.GEOSPHERE)])

cities = [{"location": {'type': 'Point', 'coordinates': [57, 2]}, "name": "Aberdeen"},
          {"location": {'type': 'Point', 'coordinates': [52, 13]}, "name": "Berlin"},
          {"location": {'type': 'Point', 'coordinates': [44, 26]}, "name": "Bucharest"},
          {"location": {'type': 'Point', 'coordinates': [40, 14]}, "name": "Napoli"},
          {"location": {'type': 'Point', 'coordinates': [48, 2]}, "name": "Paris"},
          {"location": {'type': 'Point', 'coordinates': [35, -70]}, "name": "Tokyo"},
          {"location": {'type': 'Point', 'coordinates': [47, 8]}, "name": "Zurich"}]

try:
    result = db.places.insert_many(cities)
    for doc in db.places.find( {"location":{'$nearSphere':  [57, 2], "$maxDistance": 1}}).limit(3):
        pprint.pprint(doc)
except BulkWriteError as bwe:
    print(bwe.details)

В качестве ответа я бы ожидал только Абердина, вместо этого я все равно получаю 3 ближайших, даже если максимальное расстояние больше 1 метра. Я думаю, что я делаю что-то не так. Любая помощь, а также лучшие примеры использования pymon go (лучше, чем из документации) действительно помогут. Спасибо

1 Ответ

2 голосов
/ 08 апреля 2020

Вы используете более старую форму запроса, где расстояние указано в радианах. Если вы измените на новый формат , то maxDistance указывается в метрах.

Также по причинам, потерянным в глубине веков, данные GeoSpatial сортируются в длинном / латинском порядке, поэтому все ваши координаты необходимо поменять местами. Я исправил ваш код, чтобы использовать правильную ориентацию координат, и ввел новый формат запроса. Я также вставил команду drop для коллекции (так как это пример кода). Это смутило меня и может смущать. Несколько прогонов программы будут вставлять одни и те же точки снова и снова. Без удаления каждый запрос будет возвращать столько результатов, сколько раз вы запустили программу. Наконец, я добавил индекс GEOSPHERE, в документации которого говорится, что вам нужно, даже если ваша программа работает без него. Я подозреваю, что без этого вы увидите снижение производительности геометрии c по мере увеличения количества локаций.

import pymongo
import pprint
from pymongo.errors import BulkWriteError

db = pymongo.MongoClient().geo_example
db.places.drop()
db.places.create_index([("location", pymongo.GEOSPHERE)])

cities = [{"location": {'type': 'Point', 'coordinates': [2, 57]}, "name": "Aberdeen"},
          {"location": {'type': 'Point', 'coordinates': [13, 52]}, "name": "Berlin"},
          {"location": {'type': 'Point', 'coordinates': [26, 44]}, "name": "Bucharest"},
          {"location": {'type': 'Point', 'coordinates': [14, 40]}, "name": "Napoli"},
          {"location": {'type': 'Point', 'coordinates': [2, 48]}, "name": "Paris"},
          {"location": {'type': 'Point', 'coordinates': [-70, 35]}, "name": "Tokyo"},
          {"location": {'type': 'Point', 'coordinates': [8, 47]}, "name": "Zurich"}]

try:
    result = db.places.insert_many(cities)
    db.places.create_index([("location", pymongo.GEOSPHERE)])
    for doc in db.places.find({"location":{
                                "$nearSphere": {
                                     "$geometry": {
                                        "type": "Point",
                                        "coordinates": [2,57]
                                      },
                                     "$maxDistance": 1}}}):
        pprint.pprint(doc)
except BulkWriteError as bwe:
    print(bwe.details)

...