Как найти ближайший документ с помощью API поиска Google App Engine?

У меня около 400000 документов в поисковом индексе GAE. Все документы имеют locationGeoPoint собственности и распространяются по всему земному шару. Некоторые документы могут находиться на расстоянии более 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-х точек, а затем рассчитать из этого.

Другие вопросы по тегам