2013-03-06 8 views
6

Ho circa 400.000 documenti in un indice GAE Search. Tutti i documenti hanno una proprietà locationGeoPoint e sono distribuiti su tutto il globo. Alcuni documenti potrebbero trovarsi a oltre 4000 km da qualsiasi altro documento, altri potrebbero essere raggruppati a pochi metri l'uno dall'altro.Come posso trovare il documento più vicino utilizzando l'API di ricerca di Google App Engine?

Vorrei trovare il documento più vicina ad un insieme specifico di coordinate, ma trovare il seguente codice dà risultati non corretti:

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) 

Con questo codice otterrò i risultati che sono coerenti ma non corretto. Ad esempio, una ricerca per il documento più vicino a Londra indica che il più vicino era in Scozia. Ho verificato che ci sono migliaia di documenti più vicini.

Ho ridotto il problema al parametro radius troppo grande. Ottengo risultati corretti se il raggio scende a circa 12 km (radius=12000). Generalmente non ci sono più di 1000 documenti in un raggio di 12 km. (Probabilmente associato a search.SortOptions(limit=1000).)

Il problema è che se mi trovo in una zona sparsa del globo in cui non ci sono documenti per migliaia di miglia, la mia funzione di ricerca non restituirà nulla con radius=12000 (12 km). Voglio che restituisca il documento più vicino a me ovunque io sia. Come posso farlo in modo coerente con una chiamata all'API di ricerca?

risposta

5

Credo che il problema sia il seguente. La query seleziona fino a 10.000 documenti, quindi quelli sono ordinati in base all'espressione di ordinamento a distanza e restituiti. (Ovvero, il genere non è in realtà su tutti i documenti 400k.) Quindi sospetto che alcuni dei punti geograficamente più vicini non siano inclusi in questa selezione 10k. Ecco perché le cose funzionano meglio quando si restringe il raggio di ricerca, poiché si hanno meno punti totali in quel raggio.

In sostanza, si desidera ottenere i "risultati" della query fino a 10k, in un modo che abbia senso per ciò su cui si sta effettuando la query. Si può affrontare questo in almeno un paio di modi che si possono combinare:

  • Aggiungi una classifica, in modo che i documenti piu 'importanti' (da parte di alcuni criteri che ha senso nel dominio) vengono restituiti in ordine di classifica, quindi questi saranno ordinati per distanza.
  • Filtro su uno o più campi documento (ad esempio "categoria business", se i documenti contengono informazioni sulle aziende) per ridurre il numero di documenti candidati.

(Non credo che questa soglia 10k sia attualmente nella documentazione della ricerca API, ho archiviato un ticket per ottenerlo aggiunto).

+0

Grazie per la conferma di ciò che @Middy e io presumevamo accadesse dietro le quinte. Sapere che il limite "colpisci" è 10k aiuta sicuramente. Solo per il completamento dirò la risposta a ** Voglio che restituisca il documento più vicino a me ovunque io sia. Come posso raggiungere questo risultato in modo coerente con una chiamata all'API di ricerca? ** È che non posso coerentemente se il mio raggio di ricerca _might_ contenga più di 10k documenti - che purtroppo la mia app potrebbe fare :( – Dan

1

Ho lo stesso identico problema e non credo sia possibile. Il problema si verifica come tu stesso hai capito quando ci sono più risultati possibili dei risultati restituiti. L'algoritmo di Google si chiude solo quando ha caricato i limiti e poi ordina i risultati.

Ho visto gli stessi cluster di te e la sua parte dell'API di ricerca.

Un attacco sarebbe suddividere la ricerca in sottosettori, effettuare più chiamate simultanee e quindi unire e ordinare i risultati.

+0

Da un punto di vista pragmatico, l'hack funzionerebbe se si conoscesse la densità dei cluster più densi di 'GeoPoint'. (A scapito della quota dell'API di ricerca.) Tuttavia, se non sai quanto siano densi i tuoi cluster più densi, i sottosettori potrebbero soffrire dello stesso problema di dare risultati sbagliati senza che tu lo sappia. Nel mio caso, 20.000 chiamate API di ricerca al giorno non lasciano molto spazio per il raddoppio delle chiamate per ogni richiesta dell'utente. – Dan

0

Idea selvaggia, perché non mantenere/registrare la distanza da 3 punti, quindi calcolare da quello.

Problemi correlati