2013-03-06 8 views
6

Mam około 400 000 dokumentów w indeksie GAE Search. Wszystkie dokumenty mają właściwość locationGeoPoint i są rozmieszczone na całym świecie. Niektóre dokumenty mogą znajdować się w odległości ponad 4000 km od jakiegokolwiek innego dokumentu, inne mogą być połączone w metrach od siebie nawzajem.Jak znaleźć najbliższy dokument za pomocą interfejsu Google App Engine Search API?

chciałbym znaleźć najbliższy dokument do określonego zestawu współrzędnych ale znaleźć następujący kod daje błędne wyniki:

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) 

z tym kodem będę uzyskać wyniki, które są zgodne, ale błędne. Na przykład wyszukiwanie najbliższego dokumentu do Londynu wskazuje, że najbliższy znajduje się w Szkocji. Sprawdziłem, że istnieją tysiące bliżej dokumentów.

Zawęziłem problem do zbyt dużego parametru radius. Dostaję poprawne wyniki, jeśli promień spadnie do około 12 km (radius=12000). Z reguły nie ma więcej niż 1000 dokumentów w promieniu 12 km. (Prawdopodobnie związane z search.SortOptions(limit=1000).)

Problemem jest to, że jeśli jestem w rozrzedzony obszarze kuli ziemskiej, gdzie nie ma żadnych dokumentów na tysiące mil, moja funkcja wyszukiwania nie zwraca niczego z radius=12000 (12km). Chcę, aby zwracał mi najbliższy dokument, gdziekolwiek jestem. Jak mogę to osiągnąć konsekwentnie za pomocą jednego połączenia z interfejsem API wyszukiwania?

Odpowiedz

5

Uważam, że problem jest następujący. Zapytanie wybierze do 10 KB dokumentów, następnie zostaną posortowane zgodnie z wyrażeniem sortowania odległości i zwrócone. (Oznacza to, że ten rodzaj nie jest w rzeczywistości ponad 400 tys. Dokumentów.) Tak więc podejrzewam, że niektóre z geograficznie bliskich punktów nie są uwzględnione w tej selekcji 10k. Dzięki temu rzeczy działają lepiej, gdy zawęzisz swój promień wyszukiwania, ponieważ masz mniejszą liczbę punktów w tym promieniu.

Zasadniczo chcesz, aby twoje zapytanie "trafiło" do 10 tys., W sposób, który ma sens w przypadku zapytań. Można rozwiązać to na co najmniej kilka sposobów, które można łączyć:

  • Dodaj rankingu, tak, że większość „ważnych” Docs (według pewnych kryteriów, które ma sens w domenie) zwracane są w kolejność według rankingu, a następnie sortowane według odległości.
  • Filtruj jedno lub więcej pól dokumentu (np. "Kategorię biznesową", jeśli dokumenty zawierają informacje o firmach), aby zmniejszyć liczbę dokumentów kandydatów.

(Nie wierzę, że ten próg 10k jest obecnie w dokumentacji Search API, mam zgłoszony bilet, aby go dodać).

+0

Dzięki za potwierdzenie tego, co założyli @Middy, działo się to za kulisami. Świadomość, że limit "trafień" wynosi 10k, zdecydowanie pomaga. Dopiero po ukończeniu określę odpowiedź na ** Chcę, aby zwracała mi najbliższy dokument, gdziekolwiek jestem. Jak mogę to osiągnąć konsekwentnie za pomocą jednego połączenia z interfejsem API wyszukiwania? ** jest to, że nie mogę konsekwentnie, jeśli mój promień wyszukiwania _might_ zawiera więcej niż 10 000 dokumentów - co niestety może zrobić moja aplikacja :( – Dan

1

Mam dokładnie ten sam problem i nie sądzę, że jest to możliwe. Problem występuje, ponieważ sam odkryłeś, kiedy jest więcej możliwych wyników niż wyniki zwrócone. Algorytm Google kończy działanie po załadowaniu limitów, a następnie sortuje wyniki.

Widziałem te same klastry, co Ty i jego część API wyszukiwania.

Jednym z ataków będzie podzielenie twojego wyszukiwania na podsektory, wykonywanie wielu jednoczesnych połączeń, a następnie łączenie i porządkowanie wyników.

+0

Z pragmatycznej perspektywy hack zadziałałby, gdybyś wiedział, jak gęste są twoje najgęstsze skupiska "GeoPoint". (Kosztem kwoty interfejsu API wyszukiwarki.) Jednak jeśli nie wiesz, jak gęste są twoje najgęstsze klastry, to podsektory mogą cierpieć z tym samym problemem podania błędnych wyników bez twojej wiedzy. W moim przypadku 20 000 połączeń API w trybie wyszukiwania dziennie nie pozostawia wiele miejsca na podwojenie liczby połączeń dla każdego żądania użytkownika. – Dan

0

Dziki pomysł, dlaczego nie zachować/zapisać odległość od 3 punktów, a następnie obliczyć z tego.

Powiązane problemy