Геопространственная индексация MongoDB позволяет использовать коллекцию в качестве карты. Он работает не так, как «нормальное» индексирование, но на самом деле есть хороший визуальный способ увидеть, что делает геопространственное индексирование.
Допустим, у нас есть карта 16 × 16; что-то похожее на это:
Все координаты на нашей карте (как описано выше) находятся где-то между [0,0] и [16,16], поэтому я собираюсь установить минимальное значение 0 и максимальное значение 16.
db.map.ensureIndex({point : "2d"}, {min : 0, max : 16, bits : 4})
Это по сути превращает нашу коллекцию в карту. (Не беспокойтесь о битах , сейчас я объясню это ниже.)
Допустим, у нас есть что-то в точке [4,6]. MongoDB генерирует геохэш этой точки, который описывает точку таким образом, чтобы упростить поиск объектов рядом с ней (и при этом иметь возможность распределять карту по нескольким серверам). Геохеш для этой точки представляет собой цепочку битов, описывающую положение [4,6]. Мы можем найти геохэш этой точки, разделив нашу карту на квадранты и определив, в каком квадранте она находится. Итак, сначала мы разделим карту на 4 части:
Это самая сложная часть: каждый квадрант может быть описан двумя битами, как показано в таблице ниже:
01 | 11 |
00 | 10 |
[4,6] находится в нижнем левом квадранте, что соответствует 00 в таблице выше. Таким образом, его геохэш начинается с 00.
Пока геохаш: 00
Теперь мы снова разделим этот сектор:
[4,6] теперь находится в верхнем правом квадранте, поэтому следующие два бита в геохэше равны 11. Обратите внимание, что нижний и левый края включены в квадрант, верхний и правый края исключены.
Пока геохаш: 0011
Теперь мы снова разделим этот сектор:
[4,6] теперь находится в верхнем левом квадранте, поэтому следующие два бита в геохеше — 01.
Пока геохаш: 001101
Теперь мы снова разделим этот сектор:
[4,6] теперь находится в нижнем левом квадранте, поэтому следующие два бита в геохеше — 00.
Пока что геохаш: 00110100
Вы можете задаться вопросом: как далеко мы продолжаем делиться? Это именно то, для чего предназначена установка битов . Мы установили его на 4 при создании индекса, поэтому мы делим на квадранты 4 раза. Если бы мы хотели более высокую точность, мы могли бы установить биты на что-то более высокое.
Вы можете проверить свою математику выше, используя команду geoNear , которая возвращает геохэш для точки, возле которой вы ищете:
> db.runCommand({geoNear : "map", near : [4,6]}) { "ns" : "test.map", "near" : "00110100", "results" : [ ], "stats" : { "time" : 0, "btreelocs" : 0, "nscanned" : 0, "objectsLoaded" : 0, "avgDistance" : NaN, "maxDistance" : -1 }, "ok" : 1 }
Как видите, поле «ближний» содержит именно тот геохэш, который мы ожидаем из наших расчетов.
Интересная вещь о геохэшинге состоит в том, что это позволяет легко определить, что находится рядом с нами, потому что вещи отсортированы в соответствии с их положением на карте: каждый документ с точкой геохеша, начинающейся с 00, находится в нижнем левом квадранте, каждая точка начинается с 00111111 очень близко к середине, но в левом нижнем квадранте. Таким образом, вы можете посмотреть, где находится точка, посмотрев на ее геохэш.
Биты и точность
Допустим, волшебник накладывает огненное кольцо вокруг себя с радиусом 2. Захвачена ли точка [4,6] в этом огненном кольце?
Из рисунка видно, что это не так, но если мы посмотрим на геохэш, мы на самом деле не можем сказать: [4,6] хеширует до 00110100, но то же самое делает [4.9, 6.9] и любое другое значение в квадрат между [4,6] и [5,7]. Таким образом, чтобы выяснить, находится ли точка внутри круга, MongoDB должен перейти к документу и посмотреть фактическое значение в поле точки . Таким образом, установка битов в 4 немного низка для данных, которые мы используем / запросы, которые мы делаем.
Как правило, вам не стоит беспокоиться об установке битов , я установил их выше только для демонстрации. биты по умолчанию равны 26, что дает разрешение приблизительно 1 фут с использованием широты и долготы. Чем больше число битов, тем медленнее получается геохэш (наоборот, чем меньше бит, тем быстрее геохэш, но больше доступа к документам при поиске). Если вы выполняете запросы с высоким или низким разрешением, вы можете поиграть с разными значениями битов (в dev, в репрезентативном наборе данных) и посмотреть, получите ли вы лучшую производительность.
Спасибо Грегу Штудеру , который в прошлую пятницу выступил с докладом о геопространственных технологиях и вдохновил этот пост. (Каждую пятницу инженер 10gen проводит технический разговор о том, над чем они работают, и это действительно хороший способ не отставать от всего того, что делают коллеги. Если вы когда-либо управляете техническим отделом, я очень рекомендую их!)
Источник: http://www.snailinaturtleneck.com/blog/2011/06/08/mongo-in-flatland/