2015-02-02 2 views
0

У меня есть несколько полигонов, хранящихся в GeoJSON в моем mongoDB.Оптимизация запросов GeoJSON MongoDB

Клиент отправляет список загружаемых ящиков (ящики являются ячейками регулярной сетки).

Обычный способ получить их - это сделать запрос GeoJSON с каждым полем, но он медленный, когда у меня много ящиков.

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

Дано:

box = [ [ [ 0, 0 ], [ 1, 0 ], [ 1, 1 ], [ 0, 1 ], [ 0, 0 ] ] ] // the box to load 
pks = [ ObjectId("54cf535cfe022e01ab4932f5"), ObjectId("54cf535cfe022e01ab4932f6") ] // the list of polygons already retrieved 

С MongoDB, я бы что-то вроде этого:

for box in boxes: 
    db.places.find({ points: 
     { $geoIntersects: { $geometry: { type: "Polygon" , coordinates: box } } }, 
     { _id: { $nin: pks } } 
    }) 

Я использую MongoEngine, поэтому у меня есть следующие:

pks = [] 
for box in boxes: 
    p = Polygon.objects(points__geo_intersects=box, pk__nin=pks) 
    if len(p)>0:  
     pks += p.scalar("id") 

У меня есть три вопроса :

1. Есть ли более эффективный способ запроса полигонов с помощью этого метода?

2. Было бы быстрее использовать объект Cell, содержащий список ссылок полигонов, которые лежат на ячейке?

В MongoEngine я бы следующую модель:

class Cell(Document): 
    x = DecimalField() 
    y = DecimalField() 
    polygons = ListField(ReferenceField('Polygon')) 

    meta = { 
     'indexes': [[ ("x", 1), ("y", 1) ]] 
    } 

Список коробки для загрузки бы координаты, соответствующие ячейки для загрузки.

Это дало бы с MongoEngine:

polygons = {} 

for b in boxes: 
    cell = Cell.objects.get(x=b['x'], y=b['y']) 

    for polygon in cell.polygons: 
     if not polygons.has_key(polygon.pk): 
      polygons[polygon.pk] = polygon.to_json() 

3. Есть ли более эффективный способ для запроса многоугольников с этим методом? (я думаю, что я должен использовать select_related(), и, возможно, можно отфильтровать многоугольники непосредственно в запросе MongoDB, чтобы избежать извлечения дубликатов)

+0

Я только что сделал Тест: потребовалось 2,03 секунды для извлечения моих полигонов с помощью первого метода и 0,65 секунды со вторым методом. –

+0

Hum ... На самом деле я только выяснил, что разница, вероятно, происходит от 'pk__nin = pks', которая занимает больше времени. Теперь у меня есть более быстрые результаты с первым методом ... Я продолжу расследование этого после обеда ... –

ответ

0

Сделав несколько тестов, я могу ответить на мои собственные вопросы: это не заметно быстрее для использования промежуточного объекта, такого как Cell.

Однако, используя список первичных ключей в запросе, например:

pks = [] 
for box in boxes: 
    p = Polygon.objects(points__geo_intersects=box, pk__nin=pks) 
    if len(p)>0:  
     pks += p.scalar("id") 

гораздо медленнее, чем при использовании словаря игнорировать дубликаты, например:

polygons = {} 
for box in boxes: 
    p = Polygon.objects(points__geo_intersects=box) 
    for polygon in p: 
     if not polygons.has_key(polygon.pk): 
      polygons[polygon.pk] = polygon.to_json() 
Смежные вопросы