Как найти ближайший документ с помощью API поиска Google App Engine?
У меня около 400000 документов в поисковом индексе GAE. Все документы имеют location
GeoPoint
собственности и распространяются по всему земному шару. Некоторые документы могут находиться на расстоянии более 4000 км от любого другого документа, другие могут быть сгруппированы в пределах нескольких метров друг от друга.
Я хотел бы найти ближайший документ к определенному набору координат, но найти следующий код дает неверные результаты:
from google.appengine.api import search
# coords are in the form of a tuple e.g. (50.123, 1.123)
search.Document(
doc_id='meaningful-unique-id',
fields=[search.GeoField(name='location'
value=search.GeoPoint(coords[0], coords[1]))])
# find document function radius is in metres
def find_document(coords, radius=1000000):
sort_expr = search.SortExpression(
expression='distance(location, geopoint(%.3f, %.3f))' % coords,
direction=search.SortExpression.ASCENDING,
default_value=0)
search_query = search.Query(
query_string='distance(location, geopoint(%.3f, %.3f)) < %d' \
% (coords[0], coords[1], radius),
options=search.QueryOptions(
limit=1,
ids_only=True,
sort_options=search.SortOptions(expressions=[sort_expr])))
index = search.Index(name='document-index')
return index.search(search_query)
С помощью этого кода я получу результаты, которые соответствуют, но неверны. Например, поиск ближайшего к Лондону документа показал, что ближайший был в Шотландии. Я проверил, что есть тысячи более близких документов.
Я сузил проблему до radius
параметр слишком велик. Я получаю правильные результаты, если радиус составляет около 12 км (radius=12000
). В радиусе 12 км обычно не более 1000 документов. (Вероятно, связано с search.SortOptions(limit=1000)
.)
Проблема в том, что если я нахожусь в редкой области земного шара, где нет документов на тысячи миль, моя функция поиска ничего не выдаст с radius=12000
(12 км). Я хочу, чтобы он вернул мне ближайший документ, где бы я ни был. Как я могу сделать это последовательно с одним вызовом API поиска?
3 ответа
Я считаю, что проблема заключается в следующем. Ваш запрос выберет до 10 тыс. Документов, затем они будут отсортированы в соответствии с выражением дистанционной сортировки и возвращены. (То есть на самом деле сортировка не распространяется на все документы с разрешением 400 тыс.). Поэтому я подозреваю, что некоторые географически более близкие точки не включены в этот выбор с разрешением 10 тыс. Вот почему все работает лучше, когда вы сужаете радиус поиска, так как у вас меньше общих точек в этом радиусе.
По сути, вы хотите уменьшить количество запросов до 10 тыс., Что будет иметь смысл для того, к чему вы обращаетесь. Вы можете решить эту проблему, по крайней мере, несколькими способами, которые вы можете комбинировать:
- Добавьте рейтинг, чтобы самые "важные" документы (по некоторым критериям, которые имеют смысл в вашей области) возвращались в порядке ранжирования, а затем сортируются по расстоянию.
- Отфильтруйте одно или несколько полей документа (например, "бизнес-категория", если ваши документы содержат информацию о компаниях), чтобы уменьшить количество документов-кандидатов.
(Я не верю, что этот порог 10k в настоящее время находится в документации API поиска; я подал заявку, чтобы добавить его).
У меня точно такая же проблема, и я не думаю, что это возможно. Проблема возникает, как вы сами выяснили, когда есть больше возможных результатов, чем возвращенных результатов. Алгоритм Google просто завершает работу, когда загружает ограничения, а затем сортирует результаты.
Я видел те же кластеры, что и вы, и его часть API поиска.
Один хак будет разделить ваш поиск на подсекторы, сделать несколько одновременных вызовов, а затем объединить и упорядочить результаты.
Дикая идея, почему бы не сохранить / записать расстояние от 3-х точек, а затем рассчитать из этого.