L'API Search fornisce un modello per l'indicizzazione dei documenti che contengono dati strutturati. Puoi cercare in un indice, organizzare e presentare i risultati della ricerca. L'API supporta la corrispondenza del testo completo nei campi stringa. Documenti e indici vengono salvati in un archivio permanente separato ottimizzato per le operazioni di ricerca. L'API Search può indicizzare un numero qualsiasi di documenti. App Engine Datastore potrebbe essere più appropriato per le applicazioni che devono recuperare set di risultati di grandi dimensioni.
Panoramica
L'API Search si basa su quattro concetti principali: documenti, indici, query e risultati.
Documenti
Un documento è un oggetto con un ID univoco e un elenco di campi contenenti dati utente. Ogni campo ha un nome e un tipo. Esistono diversi tipi di campi, identificati in base ai tipi di valori che contengono:
- Campo Atom: una stringa di caratteri indivisibile.
- Campo di testo: una stringa di testo normale in cui è possibile ricercare parola per parola.
- Campo HTML: una stringa che contiene tag di markup HTML, è possibile cercare solo il testo esterno ai tag di markup.
- Campo numerico: un numero in virgola mobile.
- Campo data: un oggetto data.
- Campo Geopoint: un oggetto dati con coordinate di latitudine e longitudine.
La dimensione massima di un documento è 1 MB.
Indici
Un indice archivia i documenti per recuperarli. Puoi recuperare un singolo documento in base al relativo ID, a un intervallo di documenti con ID consecutivi o a tutti i documenti in un indice. Puoi anche cercare in un indice per recuperare i documenti che soddisfano determinati criteri sui campi e i loro valori, specificati come stringa di query. Puoi gestire gruppi di documenti inserendoli in indici separati.
Non c'è limite al numero di documenti in un indice o al numero di indici che puoi utilizzare. La dimensione totale di tutti i documenti in un singolo indice è limitata a 10 GB per impostazione predefinita. Gli utenti con il ruolo Amministratore App Engine possono inviare una richiesta dalla pagina App Engine Search della console Google Cloud per incrementare le dimensioni fino a 200 GB.
Query
Per cercare in un indice, crei una query che ha una stringa di query e possibilmente alcune opzioni aggiuntive. Una stringa di query specifica le condizioni per i valori di uno o più campi del documento. Quando esegui una ricerca in un indice, ti vengono mostrati solo i documenti al suo interno con campi che soddisfano la query.
La query più semplice, a volte chiamata "ricerca globale", è una stringa che contiene solo valori dei campi. Questa ricerca utilizza una stringa che cerca documenti che contengono le parole "rosa" e "acqua":
Cerca i documenti con campi di data che contengono la data 4 luglio 1776 o campi di testo che includono la stringa "1776-07-04":
Una stringa di query può anche essere più specifica. Può contenere uno o più termini, ciascuno dei quali denomina un campo e un vincolo sul valore del campo. La forma esatta di un termine dipende dal tipo di campo. Ad esempio, supponendo che esista un campo di testo chiamato "prodotto" e un campo numerico chiamato "prezzo", ecco una stringa di query con due termini:
Le opzioni di query, come suggerisce il nome, non sono obbligatorie. Attivano una serie di funzionalità:
- Controlla il numero di documenti che vengono restituiti nei risultati di ricerca.
- Specifica quali campi dei documenti includere nei risultati. L'impostazione predefinita prevede di includere tutti i campi del documento originale. Puoi specificare che i risultati includano solo un sottoinsieme di campi (il documento originale non è interessato).
- Ordina i risultati.
- Crea "campi calcolati" per i documenti utilizzando
FieldExpressions
e campi di testo ridotto utilizzando gli snippet. - Supporta la navigazione nelle pagine dei risultati di ricerca restituendo solo una parte dei documenti corrispondenti per ogni query (utilizzando offset e cursori)
Ti consigliamo di registrare le stringhe di query nella tua applicazione se vuoi conservare un registro delle query eseguite.
Risultati di ricerca
Una chiamata al numerosearch()
può restituire solo un numero limitato di documenti corrispondenti.
La tua ricerca potrebbe trovare più documenti di quelli che possono essere restituiti in una singola chiamata. Ogni chiamata di ricerca restituisce un'istanza della classe Results
, che contiene informazioni sul numero di documenti trovati e restituiti, oltre all'elenco dei documenti restituiti. Puoi ripetere la stessa ricerca utilizzando cursors o offset per recuperare il set completo di documenti corrispondenti.
Materiale di formazione aggiuntivo
Oltre a questa documentazione, puoi leggere il corso di formazione in due parti sulla API Search nella Google Developer's Academy. (anche se la classe utilizza l'API Python, potresti trovare utile la discussione aggiuntiva sui concetti della Ricerca).
Documenti e campi
La classe Document rappresenta i documenti. Ogni documento ha un identificatore documento e un elenco di campi.Identificatore documento
Ogni documento in un indice deve avere un identificatore documento univoco o doc_id
.
L'identificatore può essere utilizzato per recuperare un documento da un indice senza eseguire una ricerca. Per impostazione predefinita, l'API Search genera automaticamente un doc_id
quando viene creato un documento. Puoi anche specificare personalmente il doc_id
quando crei un documento. Un elemento doc_id
deve contenere solo caratteri ASCII visibili e stampabili (codici ASCII da 33 a 126 inclusi) e non superare i 500 caratteri. Un identificatore di documento non può iniziare con un punto esclamativo ("!") e non può iniziare e terminare con due trattini bassi ("__").
Sebbene sia pratico creare identificatori di documenti univoci leggibili e significativi,
non puoi includere doc_id
in una ricerca. Considera questo scenario: hai un indice con documenti che rappresentano parti e che utilizza il numero di serie della parte come doc_id
. Sarà molto efficiente recuperare il documento per ogni singola parte, ma sarà impossibile cercare un intervallo di numeri di serie insieme ad altri valori di campi, ad esempio la data di acquisto. L'archiviazione del numero di serie
in un campo atomico risolve il problema.
Campi documento
Un documento contiene campi con un nome, un tipo e un singolo valore di quel tipo. Due o più campi possono avere lo stesso nome, ma tipi diversi. Ad esempio, puoi definire due campi con il nome "age": uno con tipo di testo (il valore "twenty-two") e l'altro con tipo numerico (valore 22).
Nomi dei campi
I nomi dei campi sono sensibili alle maiuscole e possono contenere solo caratteri ASCII. Devono iniziare con una lettera e possono contenere lettere, numeri o trattini bassi. Il nome di un campo non può contenere più di 500 caratteri.
Campi a più valori
Un campo può contenere un solo valore, che deve corrispondere al tipo di campo. I nomi dei campi non devono essere univoci. Un documento può avere più campi con lo stesso nome e lo stesso tipo, il che è un modo per rappresentare un campo con più valori. Tuttavia, i campi relativi a data e numeri con lo stesso nome non possono essere ripetuti. Un documento può anche contenere più campi con lo stesso nome e tipi di campi diversi.
Tipi di campo
Esistono tre tipi di campi che memorizzano stringhe di caratteri java.lang.String
;
li chiamo collettivamente come campi stringa:
- Campo di testo: una stringa di lunghezza massima 1024**2 caratteri.
- Campo HTML: una stringa in formato HTML con lunghezza massima di 1024**2 caratteri.
- Campo Atom: una stringa con lunghezza massima di 500 caratteri.
Esistono inoltre tre tipi di campi in cui sono archiviati dati non testuali:
- Campo numerico: un valore in virgola mobile a precisione doppia compreso tra -2.147.483.647 e 2.147.483.647.
- Campo data: A
java.util.Date
. - Campo Geopoint: un punto sulla Terra descritto da coordinate di latitudine e longitudine.
I tipi di campo vengono specificati utilizzando le enumerazioni di Field.FieldType
TEXT
, HTML
, ATOM
, NUMBER
, DATE
e GEO_POINT
.
Trattamento speciale dei campi stringa e di data
Quando un documento con campi di data, testo o HTML viene aggiunto a un indice, si verificano alcune azioni speciali. Per utilizzare in modo efficace l'API Search, è utile capire cosa sta succedendo.
Campi stringa di tokenizzazione
Quando un campo HTML o di testo viene indicizzato, i suoi contenuti vengono tokenizzati. La stringa viene suddivisa in token ogni volta che compaiono spazi vuoti o caratteri speciali (segni di punteggiatura, simboli del cancelletto, barra rovesciata e così via). L'indice includerà una voce per ogni token. Ciò consente di cercare parole chiave e frasi che comprendono solo una parte del valore di un campo. Ad esempio, la ricerca di "scuro" troverà un documento con un campo di testo contenente la stringa "è stata una notte buia e tempestosa", mentre la ricerca di "tempo" troverà un documento con un campo di testo contenente la stringa "questo è un sistema in tempo reale".
Nei campi HTML, il testo all'interno dei tag di markup non viene tokenizzato, pertanto un documento con un campo HTML contenente it was a <strong>dark</strong> night
corrisponderà a una ricerca per "night", ma non per "strong". Per cercare il testo del markup, archivialo in un campo di testo.
I campi Atom non sono tokenizzati. Un documento con un campo atom con il valore "maltempo" corrisponderà solo alla ricerca dell'intera stringa "maltempo". Non corrisponde solo alla ricerca di "maltempo" o "meteo".
Regole di tokenizzazione
Il trattino basso (_) e il carattere e commerciale (&) non separano le parole in token.
Questi caratteri di spaziatura separano sempre le parole in token: spazio, ritorno a capo, avanzamento a riga, tabulazione orizzontale, tabulazione verticale, feed modulo e NULL.
Questi caratteri vengono trattati come punteggiatura e suddivideranno le parole in token:
! " % ( ) * , - | / [ ] ] ^ ` : = > ? @ { } ~ $ I caratteri nella seguente tabella di solito suddividono le parole in token, ma possono essere gestiti in modo diverso a seconda del contesto in cui appaiono:
Basato su caratteri Regola <
In un campo HTML, il simbolo "minore di" indica l'inizio di un tag HTML che viene ignorato. +
Una stringa composta da uno o più segni "più" viene considerata come parte della parola se compare alla fine della parola (C++). #
Il segno "hash" viene trattato come parte della parola se è preceduto da a, b, c, d, e, f, g, j o x (a# - g# sono note musicali; j# e x# sono un linguaggio di programmazione, c# sono entrambi). Se un termine è preceduto da "#" (#google), viene trattato come un hashtag e l'hash diventa parte della parola. '
L'apostrofo è una lettera se precede la lettera "s" seguita da un'interruzione di parole, come in "cappello di John". .
Se tra le cifre è presente un punto decimale, significa che fa parte di un numero (ovvero il separatore decimale). Può anche far parte di una parola se usato in un acronimo (A.B.C). -
Il trattino fa parte di una parola se utilizzato in un acronimo (I-B-M). Tutti gli altri caratteri a 7 bit, tranne lettere e numeri ("A-Z", "a-z", "0-9"), vengono gestiti come punteggiatura e suddividere le parole in token.
Tutto il resto viene analizzato come carattere UTF-8.
Acronimi
La tokenizzazione utilizza regole speciali per riconoscere gli acronimi (stringhe come "I.B.M.", "a-b-c" o "C I A"). Un acronimo è una stringa composta da singoli caratteri alfabetici, con lo stesso carattere separatore. I separatori validi sono il punto, il trattino o qualsiasi numero di spazi. Il carattere separatore viene rimosso dalla stringa quando viene tokenizzato un acronimo. Quindi le stringhe di esempio menzionate sopra diventano i token "ibm", "abc" e "cia". Il testo originale rimane nel campo del documento.
Quando utilizzi gli acronimi, tieni presente che:
- Un acronimo non può contenere più di 21 lettere. Una stringa di un acronimo valida con più di 21 lettere verrà suddivisa in una serie di acronimi di massimo 21 lettere ciascuno.
- Se le lettere di un acronimo sono separate da spazi, tutte le lettere devono essere uguali. Gli acronimi creati con punto e trattino possono utilizzare lettere maiuscole e minuscole miste.
- Quando cerchi un acronimo, puoi inserire la forma canonica dell'acronimo (la stringa senza separatori) o l'acronimo preceduto dal trattino o dal punto (ma non entrambi) tra le lettere. Quindi il testo "I.B.M" può essere recuperato con uno qualsiasi dei termini di ricerca "I-B-M", "I.B.M" o "IBM".
Precisione del campo data
Quando crei un campo data in un
documento, ne imposti il valore su java.util.Date
.
Ai fini dell'indicizzazione e della ricerca nel campo della data, qualsiasi componente di ora viene ignorato e la data viene convertita nel numero di giorni a partire dall'1/01/1970 UTC. Ciò significa che, anche se un campo data può contenere un valore di data e ora preciso, una query sulla data può specificare solo un valore del campo data nel formato yyyy-mm-dd
. Ciò significa anche che l'ordine dei campi relativi alle date con la stessa data non è ben definito.
Altre proprietà del documento
Il ranking di un documento è un numero intero positivo che determina l'ordine predefinito dei documenti restituiti da una ricerca. Per impostazione predefinita, il ranking viene impostato al momento della creazione del documento sul numero di secondi a partire dal 1° gennaio 2011. Puoi impostare esplicitamente il ranking quando crei un documento. È una cattiva idea assegnare lo stesso ranking a più documenti e non dovresti mai assegnare lo stesso ranking a più di 10.000 documenti.
Se specifichi le opzioni di ordinamento, puoi utilizzare il ranking come chiave di ordinamento. Tieni presente che quando viene utilizzato il ranking in un'espressione di ordinamento o un'espressione di campo, viene fatto riferimento a _rank
.
La proprietà impostazioni internazionali specifica la lingua in cui vengono codificati i campi.
Per ulteriori dettagli su questi attributi, consulta la pagina di riferimento della classe Document
.
Collegamento da un documento ad altre risorse
Puoi utilizzare l'elemento doc_id
di un documento e altri campi come link ad altre risorse nell'applicazione. Ad esempio, se utilizzi Blobstore, puoi associare il documento a un BLOB specifico impostando doc_id
o il valore di un campo Atom su BlobKey dei dati.
Creazione di un documento
Per creare un documento, richiedi un nuovo generatore utilizzando il metodo Document.newBuilder()
. Quando l'applicazione ha accesso a un generatore, può specificare un identificatore documento facoltativo e aggiungere campi.
I campi, come i documenti, vengono creati utilizzando un generatore. Il metodo Field.newBuilder()
restituisce un generatore di campi che consente di specificare il nome e il valore di un campo. Il tipo di campo viene specificato automaticamente scegliendo un metodo di impostazione specifico. Ad esempio, per indicare che un campo contiene testo normale, chiama setText()
.
Il seguente codice crea un documento con campi che rappresentano un annuncio di benvenuto nel libro degli ospiti.
Per accedere ai campi all'interno del documento, utilizza getOnlyField()
:
Utilizzo di un indice
Inserimento di documenti in un indice
Quando inserisci un documento in un indice, questo viene copiato in uno spazio di archiviazione permanente e ogni suo campo viene indicizzato in base al nome, al tipo e all'doc_id
.
Il seguente esempio di codice mostra come accedere a un indice e inserire un documento al suo interno. Ecco i passaggi da seguire:
- Crea una
IndexSpec
- Crei una
SearchService
- Chiama
SearchService.getIndex()
per creare un'istanza di Index. - Chiama
Index.put()
per aggiungere il documento all'indice.
put()
. La creazione di batch è più efficiente
che aggiungere i documenti uno alla volta.
Quando inserisci un documento in un indice e l'indice contiene già un documento con lo stesso doc_id
, il nuovo documento sostituisce quello precedente. Non viene fornito
nessun avviso. Puoi chiamare
Index.get(id)
prima di creare o aggiungere un documento a un indice per verificare se esiste già una
doc_id
specifica.
Tieni presente che la creazione di un'istanza della classe Index
non garantisce l'effettiva esistenza di un indice. La prima volta che aggiungi un documento con il metodo put
, viene creato un indice permanente.
Per verificare l'effettiva esistenza di un indice prima di iniziare a utilizzarlo, utilizza il metodo SearchService.getIndexes()
.
Aggiornamento dei documenti
Un documento non può essere modificato dopo averlo aggiunto a un indice. Non puoi aggiungere o rimuovere campi o modificare il valore di un campo. Tuttavia, puoi sostituire il documento con un nuovo documento che abbia lo stesso doc_id
.
Recupero di documenti tramite doc_id
Esistono due modi per recuperare i documenti da un indice utilizzando gli identificatori dei documenti:- Utilizza
Index.get()
per recuperare un singolo documento in base alladoc_id
. - Utilizza
Index.getRange()
per recuperare un gruppo di documenti consecutivi ordinati in base al valoredoc_id
.
Ogni chiamata è illustrata nell'esempio seguente.
Cercare i documenti in base ai contenuti
Per recuperare i documenti da un indice, crea una stringa di query e chiama
Index.search()
.
La stringa di query può essere passata direttamente
come argomento oppure puoi includerla in un
oggetto Query
che viene passato come argomento.
Per impostazione predefinita, search()
restituisce i documenti corrispondenti ordinati in ordine di ranking decrescente. Per controllare il numero di documenti restituiti, come vengono ordinati o per aggiungere campi calcolati ai risultati, devi utilizzare un oggetto Query
, che contiene una stringa di query e può anche specificare altre opzioni di ricerca e ordinamento.
Eliminazione di un indice
Ogni indice è composto dai documenti indicizzati e da uno schema dell'indice. Per eliminare un indice, elimina tutti i documenti al suo interno, quindi elimina lo schema dell'indice.
Puoi eliminare i documenti in un indice specificando il doc_id
di uno o più documenti che vuoi eliminare con il metodo delete()
.
Ti consigliamo di eliminare i documenti in batch per migliorare l'efficienza. Puoi passare fino a
200 ID documento alla volta al metodo delete()
.
delete()
. Raggruppare le eliminazioni in gruppo è più efficiente che gestirle una alla volta.
Coerenza finale
Quando inserisci, aggiorni o elimini un documento in un indice, la modifica si propaga in più data center. In genere questa operazione si verifica rapidamente, ma il tempo necessario può variare. L'API Search garantisce un'eventuale coerenza. Ciò significa che, in alcuni casi, una ricerca o il recupero di uno o più documenti potrebbero restituire risultati che non riflettono le modifiche più recenti.
Determinare la dimensione di un indice
Un indice archivia i documenti per recuperarli. Puoi recuperare un singolo documento in base al relativo ID, a un intervallo di documenti con ID consecutivi o a tutti i documenti in un indice. Puoi anche cercare in un indice per recuperare i documenti che soddisfano determinati criteri sui campi e i loro valori, specificati come stringa di query. Puoi gestire gruppi di documenti inserendoli in indici separati. Non esiste alcun limite al numero di documenti in un indice o al numero di indici che puoi utilizzare. La dimensione totale di tutti i documenti in un singolo indice è limitata a 10 GB per impostazione predefinita, ma può essere aumentata fino a 200 GB inviando una richiesta dalla pagina App Engine Search della console Google Cloud. Il metodo Index.getStorageLimit()
restituisce la dimensione massima consentita di un indice.
Index.getStorageUsage()
è una stima della quantità di spazio di archiviazione utilizzata da un indice. Questo numero è una stima perché il sistema di monitoraggio dell'indice non viene eseguito continuamente; l'utilizzo effettivo viene calcolato periodicamente. Il valore storage_usage
viene regolato tra i punti di campionamento tenendo conto delle aggiunte dei documenti, ma non delle eliminazioni.
Schemi degli indici
Ogni indice ha uno schema che mostra tutti i nomi e i tipi di campi che compaiono nei documenti che contiene. Non puoi definire uno schema autonomamente. Gli schemi vengono gestiti dinamicamente e aggiornati man mano che i documenti vengono aggiunti a un indice. Uno schema semplice potrebbe avere l'aspetto seguente, in formato JSON:
{'comment': ['TEXT'], 'date': ['DATE'], 'author': ['TEXT'], 'count': ['NUMBER']}
Ogni chiave nel dizionario è il nome di un campo documento. Il valore della chiave è un elenco dei tipi di campi utilizzati con il nome di quel campo. Se hai utilizzato lo stesso nome di campo con tipi di campi diversi, lo schema elencherà più di un tipo di campo per un nome di campo, in questo modo:
{'ambiguous-integer': ['TEXT', 'NUMBER', 'ATOM']}
Una volta visualizzato in uno schema, un campo non può più essere rimosso. Non è possibile eliminare un campo, anche se l'indice non contiene più documenti con quel particolare nome di campo.
Puoi visualizzare gli schemi per i tuoi indici in questo modo: Tieni presente che una chiamata aGetIndexes()
non può restituire più di 1000 indici. Per recuperare più indici, chiama il metodo
ripetutamente, utilizzando setStartIndexName()
insieme a
GetIndexesRequest.Builder
.
Uno schema non definisce una "classe" nel senso di programmazione degli oggetti. Per quanto riguarda l'API Search, ogni documento è univoco e gli indici possono contenere diversi tipi di documenti. Se vuoi trattare raccolte di oggetti con lo stesso elenco di campi come istanze di una classe, questa è un'astrazione che devi applicare al tuo codice. Ad esempio, puoi fare in modo che tutti i documenti con lo stesso insieme di campi rimangano nel proprio indice. Lo schema dell'indice potrebbe essere visto come la definizione della classe e ogni documento nell'indice sarebbe un'istanza della classe.
Visualizzazione degli indici nella console Google Cloud
Nella console Google Cloud puoi visualizzare informazioni sugli indici delle tue applicazioni e sui documenti che contengono. Se fai clic sul nome di un indice, vengono visualizzati i documenti contenuti nell'indice. Vedrai tutti i campi dello schema definiti per l'indice; per ogni documento con un campo di quel nome, vedrai il valore del campo. Puoi anche eseguire query sui dati dell'indice direttamente dalla console.
Quote dell'API Search
L'API Search offre diverse quote gratuite:
Risorsa o chiamata API | Quota gratuita |
---|---|
Capacità di archiviazione totale (documenti e indici) | 0,25 GB |
Query | 1000 query al giorno |
Aggiunta di documenti agli indici | 0,01 GB al giorno |
L'API Search impone questi limiti per garantire l'affidabilità del servizio. Queste norme si applicano alle app gratuite e a pagamento:
Risorsa | Quota di sicurezza |
---|---|
Utilizzo massimo delle query | 100 minuti aggregati di tempo di esecuzione delle query al minuto |
Numero massimo di documenti aggiunti o eliminati | 15.000 al minuto |
Dimensioni massime per indice (numero illimitato di indici consentiti) | 10 GB |
L'utilizzo dell'API viene conteggiato in modi diversi a seconda del tipo di chiamata:
Index.search()
: ogni chiamata API viene conteggiata come una query; il tempo di esecuzione è equivalente alla latenza della chiamata.Index.put()
: quando aggiungi documenti per indicizzare le dimensioni di ogni documento, il numero di documenti viene conteggiato ai fini della quota di indicizzazione.- Tutte le altre chiamate all'API Search vengono conteggiate in base al numero di operazioni che comportano:
SearchService.getIndexes()
: viene conteggiata un'operazione per ogni indice effettivamente restituito o un'operazione se non viene restituito nulla.Index.get()
eIndex.getRange()
: 1 operazione conteggiata per ogni documento effettivamente restituito o 1 operazione se non viene restituito nulla.Index.delete()
: 1 operazione conteggiata per ogni documento nella richiesta o 1 operazione se la richiesta è vuota.
La quota per la velocità effettiva delle query è imposta in modo che un singolo utente non possa monopolizzare il servizio di ricerca. Poiché le query possono essere eseguite contemporaneamente, ogni applicazione può eseguire query che consumano fino a 100 minuti di tempo di esecuzione per un minuto di tempo di orologio. Se esegui molte query brevi, probabilmente non raggiungerai questo limite. Una volta superata la quota, le query successive non andranno a buon fine fino alla successiva sezione temporale, quando la quota viene ripristinata. La quota non è impostata in modo rigoroso per sezioni di un minuto; viene utilizzata una variante dell'algoritmo dei bucket a perdita per controllare la larghezza di banda di ricerca con incrementi di cinque secondi.
Per ulteriori informazioni sulle quote, consulta la pagina Quote. Quando un'app cerca di superare questi importi, viene restituito un errore di quota insufficiente.
Tieni presente che, sebbene questi limiti vengano applicati al minuto, la console visualizza i totali giornalieri per ciascuno. I clienti con assistenza Silver, Gold o Platinum possono richiedere limiti di velocità effettiva più elevati contattando il proprio rappresentante dell'assistenza.
Prezzi dell'API Search
Per l'utilizzo oltre le quote gratuite vengono applicati i seguenti costi:
Risorsa | Costo |
---|---|
Capacità di archiviazione totale (documenti e indici) | 0,18 $ per GB al mese |
Query | 0,50 $ per 10.000 query |
Indicizzazione dei documenti disponibili per la ricerca | 2,00 $ per GB |
Ulteriori informazioni sui prezzi sono disponibili nella pagina Prezzi.