Chi ha bisogno di una potente ricerca full text nor­mal­men­te sceglie Apache Solr. No­no­stan­te tale processo rimanga tuttora una buona scelta, dal 2010 il mercato offre un’al­ter­na­ti­va in­te­res­san­te: Ela­stic­search. Come Solr, Ela­stic­search è basato su Apache Lucene, ma è fornito di ulteriori fun­zio­na­li­tà. Vi spie­ghia­mo le fun­zio­na­li­tà del server di ricerca e nel nostro tutorial su Ela­stic­search chiariamo come im­ple­men­ta­re la ricerca full text per il vostro progetto.

Ela­stic­search è diventato uno dei più im­por­tan­ti motori di ricerca full text su Internet. Anche le grandi aziende uti­liz­za­no questo software: Facebook, ad esempio, ha lavorato con successo per diversi anni con Ela­stic­search; anche GitHub, Netflix, Soun­d­Cloud e Zalando si affidano a questo motore di ricerca di successo.

Che cos’è Ela­stic­search?

Data la quantità di in­for­ma­zio­ni presenti su alcuni siti web, è possibile garantire un’elevata usabilità im­ple­men­tan­do una ricerca full text fun­zio­nan­te. Chi non desidera uti­liz­za­re le soluzioni di Google o Bing per offrire ai propri vi­si­ta­to­ri una funzione di ricerca, deve in­cor­po­rar­ne una propria, ad esempio con Ela­stic­search: il progetto open source è basato su Apache Lucene, anch’esso di­spo­ni­bi­le gra­tui­ta­men­te.

Ela­stic­search offre i vantaggi dello stabile pre­de­ces­so­re e li espande con fun­zio­na­li­tà ag­giun­ti­ve. Proprio come con Lucene, la ricerca funziona at­tra­ver­so un indice: anziché esaminare tutti i documenti durante una ricerca, il programma controlla un indice dei documenti creato in pre­ce­den­za in cui è ar­chi­via­to tutto il contenuto. Questo processo richiede molto meno tempo rispetto alla ricerca tra tutti i documenti.

Mentre con Lucene avete completa libertà su dove e come uti­liz­za­re la ricerca full text, con questo software occorre iniziare com­ple­ta­men­te da zero. Ela­stic­search d’altra parte vi permette di iniziare più ve­lo­ce­men­te sul World Wide Web. Con Ela­stic­search è possibile creare un server di ricerca stabile in breve tempo che può essere anche fa­cil­men­te di­stri­bui­to su più macchine.

Molti nodi (server diversi) si uniscono per formare un cluster. Viene uti­liz­za­to il co­sid­det­to shard, ovvero una par­ti­zio­ne del database: Ela­stic­sarch scompone l’indice e di­stri­bui­sce le singole parti (shards) su più nodi. Ciò divide anche il carico di lavoro. Per i progetti di grandi di­men­sio­ni la ricerca full text è inoltre molto più stabile. Per una maggiore sicurezza è possibile copiare i frammenti su più nodi.

Come Lucene, Ela­stic­search si basa sul lin­guag­gio di pro­gram­ma­zio­ne Java orientato agli oggetti. Il motore di ricerca genera risultati in formato JSON e li consegna tramite un servizio web REST. L’API rende molto facile mettere la funzione di ricerca in un sito web.

Inoltre la fun­zio­na­li­tà Ela­stic­search offre con Kibana, Beats e Logstash, co­no­sciu­ti nel loro insieme come elastic stack, dei pratici servizi ag­giun­ti­vi che con­sen­to­no di ana­liz­za­re la ricerca full text. L’azienda Elastic che sviluppa El­stic­search è fondata dal creatore del programma e offre anche servizi a pagamento come il cloud hosting.

Che cosa offre Ela­stic­search che Google & Co. non hanno?

Come tutti sappiamo Google offre già una popolare funzione di ricerca, tra l’altro fa­cil­men­te in­te­gra­bi­le nel vostro sito web. Allora perché fare una scelta più mac­chi­no­sa co­struen­do il proprio motore di ricerca con Ela­stic­search? Una possibile risposta è che con Google Custom Search (GCS) si diventa di­pen­den­ti dal gigante dei motori di ricerca e si ac­con­sen­te (almeno nella versione gratuita) a inserire pub­bli­ci­tà nei risultati di ricerca. Con Ela­stic­search potete evitare questo in­con­ve­nien­te: il codice è open source e la funzione di ricerca full text è quindi anche vostra. In questo modo non dipendete da nessuno.

Inoltre potete per­so­na­liz­za­re Ela­stic­search a vostro pia­ci­men­to. Ad esempio, se gestite la vostra piat­ta­for­ma online o il vostro negozio online, potete impostare la funzione di ricerca in modo da poter uti­liz­za­re Ela­stic­search per ricercare i profili degli utenti che hanno ef­fet­tua­to l’accesso. In tali ap­pli­ca­zio­ni il GCS raggiunge i propri limiti.

Ela­stic­search vs Apache Solr: quali sono le prin­ci­pa­li dif­fe­ren­ze?

Sia Ela­stic­search che Apache Solr sono basati su Lucene, ma sono stati svi­lup­pa­ti in offerte in­di­pen­den­ti. Tuttavia molti utenti si stanno chiedendo quale progetto scegliere. Anche se Ela­stic­search è un po’ più giovane e di­ver­sa­men­te da Solr non è sup­por­ta­to dalla community di Apache, il progetto ha superato il numero di utenti del con­cor­ren­te. La ragione di ciò è da ri­cer­car­si so­prat­tut­to nella maggiore sem­pli­ci­tà d’im­ple­men­ta­zio­ne. Inoltre Ela­stic­search è par­ti­co­lar­men­te popolare per la gestione dei dati dinamici: at­tra­ver­so uno speciale processo di me­mo­riz­za­zio­ne nella cache, Ela­stic­search riesce a ottenere che le modifiche non debbano ne­ces­sa­ria­men­te essere immesse nell’intera cache globale: è suf­fi­cien­te invece cambiare un piccolo segmento. Ciò rende Ela­stic­search un’al­ter­na­ti­va più fles­si­bi­le.

Alla fine, tuttavia, la decisione ha spesso solo a che fare con i diversi approcci open source. Solr è pie­na­men­te impegnata nella filosofia della Apache Software Foun­da­tion: Community over Code. Ogni con­tri­bu­to al codice viene preso sul serio e la community decide insieme quali aggiunte e sviluppi finiranno nel codice finale. Lo sviluppo di Ela­stic­search è diverso: anche questo progetto è open source ed è offerto con licenza Apache gratuita, ma soltanto il team di Elastic decide quali modifiche faranno parte del codice. Alcuni svi­lup­pa­to­ri non ap­prez­za­no questa mentalità ga­te­kee­per e pre­fe­ri­sco­no ri­vol­ger­si a Solr.

Tutorial per Ela­stic­search

Prima di iniziare a lavorare con Ela­stic­search si consiglia in­nan­zi­tut­to di ap­pren­de­re alcuni concetti di base. Ad esempio è degna di nota la struttura delle in­for­ma­zio­ni:

  • Index: una query di ricerca su Ela­stic­search non si applica mai al contenuto stesso, ma sempre all’indice, dove tutti i contenuti di tutti i documenti sono me­mo­riz­za­ti e già preparati, quindi la ricerca richiede poco tempo. Si tratta di un co­sid­det­to codice invertito: per ogni termine di ricerca è assegnato il luogo in cui è possibile trovare il termine.
  • Document: l’output dell’indice sono i documenti in cui sono trovati i dati. Non devono essere ne­ces­sa­ria­men­te testi completi (ad esempio, articoli di blog), bastano semplici file con­te­nen­ti in­for­ma­zio­ni.
  • Field: un documento è composto da diversi campi. Oltre al campo del contenuto attuale, anche altri metadati ap­par­ten­go­no a un documento. Ad esempio, con Ela­stic­search è possibile cercare in modo specifico i metadati relativi all’autore o al momento della creazione.

Quando parliamo di mo­di­fi­ca­re i dati si tratta di to­ke­ni­zing: un algoritmo crea i termini in­di­vi­dua­li da un testo completo. Per una macchina non esistono cose come le parole: un testo è co­sti­tui­to da una lunga stringa di segni e una lettera per un computer ha lo stesso valore di uno spazio. Affinché un testo sia. elaborato in modo si­gni­fi­ca­ti­vo, esso deve essere prima suddiviso in token. Ad esempio gli whi­te­spa­ce, quindi spa­zia­tu­re e righe vuote, sono con­si­de­ra­ti come marker per le parole. Inoltre, nella pre­pa­ra­zio­ne si effettua anche la nor­ma­liz­za­zio­ne: le parole vengono scritte uni­for­me­men­te minuscole e la pun­teg­gia­tu­ra è ignorata. Ela­stic­search ha ereditato tutti questi metodi da Apache Lucene.

N.B.

Nel seguente tutorial stiamo lavorando con la versione 6.3.0 di Ela­stic­search. Se si utilizza una versione diversa, alcuni esempi di codice o passagi del tutorial po­treb­be­ro fun­zio­na­re in modo dif­fe­ren­te.

In­stal­la­zio­ne

I file necessari per Ela­stic­search sono di­spo­ni­bi­li gra­tui­ta­men­te sul sito web ufficiale di Elastic. Qui i file sono offerti come pacchetti ZIP o tar.gz, motivo per cui possono essere fa­cil­men­te in­stal­la­ti tramite console su Linux e Mac.

N.B.

Elastic offre Ela­stic­search in due pacchetti diversi. La versione standard include anche funzioni a pagamento in prova per un certo periodo di tempo. Invece i pacchetti eti­chet­ta­ti con OSS (Open Source Software) con­ten­go­no solo com­po­nen­ti gratuiti ri­la­scia­ti con licenza Apache 2.0.

Per ZIP:

wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-oss-6.3.0.zip
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-oss-6.3.0.zip.sha512
shasum -a 512 -c elasticsearch-oss-6.3.0.zip.sha512 
unzip elasticsearch-oss-6.3.0.zip
cd elasticsearch-6.3.0

Per tar.gz:

wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-oss-6.3.0.tar.gz
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-oss-6.3.0.tar.gz.sha512
shasum -a 512 -c elasticsearch-oss-6.3.0.tar.gz.sha512 
tar -xzf elasticsearch-oss-6.3.0.tar.gz
cd elasticsearch-6.3.0

In­nan­zi­tut­to scaricate il pacchetto e la checksum dell’hash (SHA512) che con­trol­le­re­te anche nel terzo passo. Quindi de­com­pri­me­te il pacchetto e passate alla cartella ap­pro­pria­ta.

Anche l’archivio ZIP si può scaricare e uti­liz­za­re per l’in­stal­la­zio­ne su Windows, poiché il pacchetto contiene un file batch che potete eseguire. In al­ter­na­ti­va, Elastic ora fornisce anche un programma di in­stal­la­zio­ne MSI, che si trova però ancora in fase beta. Il file di in­stal­la­zio­ne di quest’ultimo contiene un’in­ter­fac­cia grafica che guida l’utente nell’in­stal­la­zio­ne.

N.B.

Poiché Ela­stic­search è basato su Java, il vostro sistema deve avere in­stal­la­to questo lin­guag­gio di pro­gram­ma­zio­ne. Potete scaricare gra­tui­ta­men­te il Java De­ve­lo­p­ment Kit (JDK) dal sito web ufficiale.

Ora eseguite Ela­stic­search dalla console navigando nella cartella bin e digitando “ela­stic­search” su Linux, Mac o Windows. Quindi aprite un browser di vostra scelta e chiamate la seguente porta dell’host locale: 'http://localhost:9200/'. Se avete in­stal­la­to cor­ret­ta­men­te Ela­stic­sarch e Java è impostato cor­ret­ta­men­te, ora dovreste essere in grado di accedere alla ricerca full text.

Con Ela­stic­search co­mu­ni­ca­te tramite l’API REST, perciò vi occorre un client ap­pro­pria­to. Si consiglia di uti­liz­za­re Kibana per questo scopo (anche un’offerta gratuita open source di Elastic va bene). Con questo programma potete uti­liz­za­re Ela­stic­search di­ret­ta­men­te nel browser. Per farlo basta andare su http://localhost:5601/ e accedere a un’in­ter­fac­cia utente grafica. Nel nostro tutorial su Kibana vi spie­ghia­mo come in­stal­la­re cor­ret­ta­men­te Kibana. In Kibana e in qualsiasi altro client potete uti­liz­za­re i metodi HTTP PUT, GET, POST e DELETE per inviare comandi alla vostra ricerca full text.

Index

Come primo passo dovete in­nan­zi­tut­to creare il vostro indice e ali­men­tar­lo con dati. È possibile uti­liz­za­re due diversi metodi HTTP: POST e PUT. Si utilizza PUT se si desidera spe­ci­fi­ca­re un par­ti­co­la­re ID per la voce. Con POST Ela­stic­search crea da sé un ID. Nel nostro esempio, vorremmo creare una bi­blio­gra­fia. Ogni voce deve contenere il nome dell’autore, il titolo dell’opera e l’anno di pub­bli­ca­zio­ne.

POST bibliography/novels
{
"author": "Isabel Allende",
"title": "The house of the spirits",
"year": "1982"
}

Se si desidera uti­liz­za­re l’input in questo modo, è ne­ces­sa­rio uti­liz­za­re la console Kibana. Se non si desidera uti­liz­za­re questo software, in al­ter­na­ti­va è possibile uti­liz­za­re cURL. Invece del comando pre­ce­den­te, immettete quanto segue nella riga di comando:

curl -XPOST http://localhost:9200/bibliography/novels -H "Content-Type: application/json" -d '{"author": "Isabel Allende", "title": "The house of the spirits", "year": "1982"}'

Di seguito vi mostriamo solo il codice per Kibana, ma si può fa­cil­men­te tra­sfe­ri­re nella sintassi di cURL. Ela­stic­search dovrebbe, se avete inserito tutto cor­ret­ta­men­te, re­sti­tui­re le seguenti in­for­ma­zio­ni all’inizio del messaggio:

{
	"_index": "bibliography",
	"_type": "novels",
	"_id": "AKKKIWQBZat9Vd0ET6N1",
	"_version": 1,
	"result": "created",
}

A questo punto dovrebbe essere chiaro che Ela­stic­search troverà un indice con il nome bi­blio­gra­phy e il tipo novels. Poiché abbiamo uti­liz­za­to il metodo POST, Ela­stic­search ha generato au­to­ma­ti­ca­men­te un ID univoco per la nostra voce. La voce è at­tual­men­te nella prima versione ed è stata creata (created) da poco.

N.B.

All’inizio il tipo (_type) era un genere di sot­to­ca­te­go­ria in Ela­stic­search. At­tra­ver­so di esso era possibile as­sem­bla­re diversi tipi sotto un solo indice. Tuttavia questo ha portato a vari problemi e quindi Elastic sta pia­ni­fi­can­do di smettere di uti­liz­za­re tali tipi. Nella versione 6.x è ancora incluso _type, ma non è più possibile as­sem­bla­re più tipi sotto un solo indice. A partire dalla versione 7.0 si pianifica di can­cel­la­re com­ple­ta­men­te i tipi, come spiegano gli svi­lup­pa­to­ri nel loro blog.

Potete anche usare PUT per dare alla vostra voce un ID specifico. Esso viene definito nella prima riga del codice. È ne­ces­sa­rio PUT anche se si desidera mo­di­fi­ca­re una versione esistente.

PUT bibliography/novels/1
{
"author": "William Gibson",
"title": "Neuromancer",
"year": "1984"
}

Il seguente output è molto simile a quello che otteniamo con il nostro metodo POST, tuttavia Ela­stic­search ci fornisce l’ID che abbiamo dato alla voce nella prima riga. L’ordine delle spe­ci­fi­che è sempre _index/_type/_id.

{
	"_index": "bibliography",
	"_type": "novels",
	"_id": "1",
	"_version": 1,
	"result": "created",
}

Con il comando PUT e l’ID univoco possiamo anche mo­di­fi­ca­re le voci:

PUT bibliography/novels/1
{
"author": "William Gibson",
"title": "Count Zero",
"year": "1986"
}

Poiché la voce con l’ID 1 esiste già, Ela­stic­search la modifica soltanto anziché crearne una nuova. Questo si riflette anche nell’output:

{
	"_index": "bibliography",
	"_type": "novels",
	"_id": "1",
	"_version": 2,
	"result": "updated",
}

Il numero di versione è aumentato a 2 e come risultato riceviamo updated al posto di created. Potete ov­via­men­te fare lo stesso con un ID creato ca­sual­men­te da Ela­stic­search, ma la lunghezza e la con­fu­sio­ne dei segni ren­de­reb­be il lavoro suc­ces­si­vo molto più com­pli­ca­to. Il processo significa anche che Ela­stic­search so­vra­scri­ve sem­pli­ce­men­te una voce se per esempio con­fon­de­te i numeri ID. Per evitare modifiche ac­ci­den­ta­li potete uti­liz­za­re l’endpoint _create:

PUT bibliography/novels/1/_create
{
"author": "Mary Shelley",
"title": "Frankenstein; or, The Modern Prometheus",
"year": "1818"
}

Poiché nell’indice esiste già una voce con ID 1, ri­ce­ve­re­te un messaggio di errore.

Se apportate modifiche a una voce come descritto sopra, creerete una voce com­ple­ta­men­te nuova in senso stretto e dovrete quindi anche compilare tutti i dettagli, al­tri­men­ti potete soltanto integrare le modifiche alla voce esistente. Per questo si utilizza l’endpoint _update:

POST bibliography/novels/1/_update
{
"doc": {
	"author": "Franz Kafka",
"genre": "Horror"
	}
}

Ora abbiamo aggiunto un ulteriore campo alla voce e mo­di­fi­ca­to un campo esistente senza però eliminare gli altri, tuttavia solo in primo piano. In back­ground infatti Ela­stic­search ha ricreato l’intera voce inserendo au­to­no­ma­men­te i contenuti già esistenti.

In linea di principio abbiamo sem­pli­ce­men­te scritto una voce in un database in modo da poterla ri­chia­ma­re di­ret­ta­men­te. Per farlo uti­liz­zia­mo il metodo GET:

GET bibliography/novels/1

Potete però anche farvi mostrare l’in­se­ri­men­to co­mo­da­men­te sul browser:

http://localhost:9200/bibliography/novels/1

Ela­stic­search ci mostra in output tutti i dettagli della nostra voce:

{
	"_index": "bibliography",
	"_type": "novels",
	"_id": "1",
	"_version": 2,
	"found": true,
	"_source": {
		"author": "William Gibson",
		"title": “Count Zero",
		"year": "1984"
	}
}

Oltre alle in­for­ma­zio­ni già note, sotto _source trovate i campi del documento. Inoltre Ela­stic­search ci informa che è stata ef­fet­ti­va­men­te trovata una voce. Se tentate di ri­chia­ma­re una voce ine­si­sten­te, non sarà vi­sua­liz­za­to alcun messaggio di errore. Invece Ela­stic­search segnala “found”: false e non ci sono voci sotto _source.

Avete inoltre anche la pos­si­bi­li­tà di tra­sci­na­re solo alcune in­for­ma­zio­ni dal database. Sup­po­nia­mo che abbiate me­mo­riz­za­to non soltanto i dati bi­blio­gra­fi­ci nel vostro indice, ma anche il testo completo di ciascun romanzo re­gi­stra­to. Anche questo sarebbe incluso in una semplice richiesta GET. Ma poniamo che al momento vi interessi soltanto il nome dell’autore e il titolo dell’opera. Potete quindi chiedere espres­sa­men­te soltanto dopo:

GET bibliography/novels/1?_source=author,title

Se non vi in­te­res­sa­no i metadati di una voce, potete vi­sua­liz­za­re anche solo il contenuto:

GET bibliography/novels/1/_source

Sup­po­nia­mo che voi non vogliate ri­chia­ma­re soltanto una singola voce nel vostro indice, bensì diverse. Ela­stic­search ha im­ple­men­ta­to l’endpoint _mget (per multi-get). Se lo uti­liz­za­te, spe­ci­fi­ca­te un array di più ID:

GET bibliography/novels/_mget
{
	"ids": ["1", "2", "3"]
}

Anche se una voce non esiste, la richiesta non rimarrà com­ple­ta­men­te ine­se­gui­ta, poiché saranno vi­sua­liz­za­ti tutti i dati esistenti. Per quanto riguarda i dati ine­si­sten­ti, Ela­stic­search comunica di non essere in grado di trovarli. La can­cel­la­zio­ne di una voce funziona in modo molto simile al richiamo di una voce. Tuttavia, invece di lavorare con GET, si lavora con DELETE:

DELETE /bibliography/novels/1

Nel seguente output, Ela­stic­search vi dice che ha trovato la voce sotto l’ID spe­ci­fi­ca­to:

{
	"_index": "bibliography",
	"_type": "novels",
	"_id": "1",
	"_version": 5,
	"result": "deleted",
}

Inoltre il programma aumenta il numero di versione di uno. Questo per due ragioni:

  1. Ela­stic­search con­tras­se­gna la voce solo come can­cel­la­ta e non la rimuove di­ret­ta­men­te dal disco rigido. La voce scom­pa­ri­rà solo nell’ulteriore corso dell’in­di­ciz­za­zio­ne.
  2. Quando si lavora con indici di­stri­bui­ti su più nodi, il controllo det­ta­glia­to delle versioni è estre­ma­men­te im­por­tan­te: ecco perché Ela­stic­search segna ogni cam­bia­men­to come una nuova versione, cam­bia­men­ti che com­pren­do­no anche l’ordine di can­cel­la­zio­ne.

È possibile apportare modifiche anche solo a un numero di versione specifico a voi noto. Se nel cluster esiste già una versione più recente rispetto a quella spe­ci­fi­ca­ta, il tentativo di modifica genererà un messaggio di errore.

PUT bibliography/novels/1?version=3
{
"author": "Marcel Proust",
"title": " À la recherche du temps perdu",
"year": "1927"
}

Non soltanto potete ri­chia­ma­re più voci con­tem­po­ra­nea­men­te, ma con il comando _bulk potete anche crearne ed eli­mi­nar­ne molte.

POST bibliography/novels/_bulk
{"delete": {"_id": "1"}}
{"create": {"_id": "1"}}
{"author": "Johann Wolfgang von Goethe", "title": "Die Leiden des jungen Werther", "year": "1774"}
{"create": {"_id": "2"}}
{"author": "Umberto Eco", "title": "Il nome della rosa", "year": "1980"}
{"create": {"_id": "3"}}
{"author": "Margaret Atwood", "title": "The Handmaid’s Tale", "year": "1985"}

Ogni ordine ottiene la propria linea: in­nan­zi­tut­to spe­ci­fi­ca­te quale azione debba essere eseguita (create, index, update, delete). Inoltre si specifica anche quale voce si desidera creare e in quale posizione. È anche possibile che un’istru­zio­ne di questo tipo funzioni con diversi indici. Per farlo dovreste lasciare vuoto il percorso verso POST e assegnare a ciascuna azione il proprio percorso. Durante la creazione delle voci è ne­ces­sa­rio spe­ci­fi­ca­re, anche in una nuova riga, un request body, nel quale risiede il contenuto della voce. L’istru­zio­ne DELETE non richiede request body di richiesta, poiché la voce completa viene can­cel­la­ta.

Finora negli esempi abbiamo sempre spe­ci­fi­ca­to i contenuti allo stesso modo, in­di­pen­den­te­men­te dal campo: Ela­stic­search ha in­ter­pre­ta­to tutte le in­for­ma­zio­ni con una stringa in­ter­con­nes­sa. Pertanto esiste un mapping in Ela­stic­search. Ciò determina come gli algoritmi debbano in­ter­pre­ta­re un input. Usate il seguente codice per vedere quale mappatura è at­tual­men­te in uso nel vostro indice:

GET bibliography/novels/_mapping

Tutti i campi sono assegnati a tipi di testo e parole chiave. Ela­stic­search ha 6 core datatypes e ancora più campi speciali. I 6 tipi prin­ci­pa­li sono in parte suddivisi in ulteriori sot­to­ca­te­go­rie:

  • string: include sia testo che keyword. Mentre le parole chiave sono con­si­de­ra­te cor­ri­spon­den­ze esatte, Ela­stic­search presume che il testo debba essere ana­liz­za­to prima di poter essere uti­liz­za­to.
  • numeric: Ela­stic­search riconosce diversi valori numerici che dif­fe­ri­sco­no prin­ci­pal­men­te per l’ambito. Ad esempio mentre il tipo byte può assumere valori tra -128 e 127 con long si ha un margine compreso tra -263 bis 263-1.
  • date: una data può essere spe­ci­fi­ca­ta gior­nal­men­te o anche con un orario preciso. Inoltre si ha la pos­si­bi­li­tà di spe­ci­fi­ca­re una data nel formato temporale Unix: secondi o mil­li­se­con­di dal 1. 1. 1970.
  • boolean: i campi for­mat­ta­ti come booleani possono avere valore vero (true) o falso (false).
  • binary: in tali campi è possibile me­mo­riz­za­re dati binari. Per inviarli usate la codifica Base64.
  • range: in questo modo spe­ci­fi­ca­te un’area. Essa può giacere tra due valori numerici, due date o anche tra due indirizzi IP.

Queste sono le categorie prin­ci­pa­li che pro­ba­bil­men­te userete più spesso. Per altri tipi con­sul­ta­te la do­cu­men­ta­zio­ne Ela­stic­search. I singoli tipi dif­fe­ri­sco­no so­prat­tut­to per il fatto che sono o exact-value o full text. Ela­stic­search comprende il contenuto del campo come input esatto oppure come contenuto che deve essere elaborato per primo. Nel corso della mappatura anche l’analyzing è im­por­tan­te: l’analisi di un contenuto è suddivisa in to­ke­ni­zing e nor­ma­li­sing:

  • To­ke­ni­zing: i token in­di­vi­dua­li sono fatti a partire da un solo testo. Essi possono includere parole singole ma anche termini fissi co­sti­tui­ti da più parole.
  • Nor­ma­li­zing: i token sono nor­ma­liz­za­ti ri­du­cen­do­li in lettere minuscole e alle loro forme base.

Per eseguire questa procedura Ela­stic­search utilizza gli Analyzer. Se includete un documento nell’indice e avete eseguito cor­ret­ta­men­te il vostro mapping, tutti i contenuti saranno esclusi cor­ret­ta­men­te nell’indice invertito. Per uti­liz­za­re la mappatura dovete creare un indice com­ple­ta­men­te nuovo: non è possibile mappare campi già esistenti.

PUT bibliography
{
	"mappings": {
		"novels": {
			"properties": {
				"author": {
					"type": "text",
					"analyzer": "simple"
				},
				"title": {
					"type": "text",
					"analyzer": "standard"
				},
				"year": {
					"type": "date",
					"format": "year"
				}
			}
		}
}
}

Abbiamo definito i due campi author e title come testo e quindi come full text. Pertanto essi hanno ancora bisogno di un analyzer adatto. Mentre forniamo l’analyzer standard al campo per il titolo del romanzo, scegliamo per il nome dell’autore il meno complesso simple analyzer. Tuttavia definiamo l’anno di pub­bli­ca­zio­ne come date, e perciò come exact-value. Poiché Ela­stic­search accetta come formato standard una voce co­sti­tui­ta da anno, mese e giorno, variamo questa ca­rat­te­ri­sti­ca, dal momento che vogliamo limitarci a spe­ci­fi­ca­re l’anno.

Ricerca

Nel capitolo pre­ce­den­te abbiamo uti­liz­za­to Ela­stic­search e il suo indice prin­ci­pal­men­te come database. Il vero vantaggio di Ela­stic­search, tuttavia, risiede nella ricerca full text. In altre parole, invece di digitare l’ID di un documento e ri­chia­ma­re così la voce, ora im­po­stia­mo Ela­stic­search in modo che possiate cercare spe­ci­fi­ca­men­te il contenuto. Per uti­liz­za­re il motore di ricerca il programma ha fornito l’endpoint _search. Com­bi­nan­do­lo con il metodo GET è possibile ad esempio vi­sua­liz­za­re tutte le voci:

GET bibliography/novels/_search
Fatto

Per ricerche più complesse, _search utilizza un body in parentesi graffe. Tuttavia alcuni server http non prevedono questo tipo di metodo GET. Pertanto gli svi­lup­pa­to­ri hanno deciso che tali ricerche fun­zio­ni­no anche come POST.

Potete anche lasciare il percorso vuoto per cercare tutti gli indici esistenti. Nell’output troverete le in­for­ma­zio­ni in­te­res­san­ti sotto hits:

"hits": {
	"total": 3,
	"max_score": 1,
	"hits": [
		{
			"_index": "bibliography",
			"_type": "novels",
			"_id": "2",
			"_score": 1,
			"_source": {
				"author": "Umberto Eco",
				"title": "Il nome della rosa",
				"year": "1980"
			}
		},
	],
	}
}

Tutte le altre voci nel nostro indice saranno anche elencate nell’output (e omesse qui per motivi di chiarezza). Il feedback di Ela­stic­search ci fornisce due ulteriori in­for­ma­zio­ni oltre ai contenuti effettivi, che possono aiutarci a com­pren­de­re la ricerca full text:

  • hits: ogni voce che cor­ri­spon­de ai criteri di ricerca viene valutata da Ela­stic­search come hit. Il programma mostra inoltre il numero di hit. Poiché nel nostro esempio ci sono 3 voci nell’indice e vogliamo vi­sua­liz­zar­le tutte, si applica "total": 3.
  • score: sotto forma di punteggio, Ela­stic­search indica quanto sia rilevante la voce della nostra richiesta. Dal momento che abbiamo sem­pli­ce­men­te cercato tutti i post nel nostro esempio, tutti hanno anche lo stesso score di 1. Le voci sono ordinate nei risultati della ricerca in ordine di per­ti­nen­za de­cre­scen­te.

Inoltre Ela­stic­search fornisce nella risposta altre in­for­ma­zio­ni su quanti shards sono coinvolti nei risultati della ricerca, su quanti mil­li­se­con­di ha impiegato la ricerca e se si sia ve­ri­fi­ca­to un timeout.

Ela­stic­search mostra per im­po­sta­zio­ne pre­de­fi­ni­ta solo i primi 10 risultati di ricerca. Tuttavia potete in­fluen­zar­lo im­po­stan­do i parametri:

  • size: quanti risultati dovrebbe mostrare Ela­stic­search?
  • from: quante voci dovrebbe saltare il programma prima di vi­sua­liz­zar­le?

Se ora avete visto soltanto i primi 10 risultati di ricerca e volete vedere soltanto i seguenti 15, dovrete uti­liz­za­re una com­bi­na­zio­ne di entrambi i parametri:

GET bibliography/novels/_search?size=15&from=10

Ela­stic­search distingue tra due diversi tipi di ricerca: da una parte utilizza una versione lite, mentre dall’altra una variante più complessa che funziona con la query DSL, una lingua di ricerca specifica. Per la versione Lite inserite la vostra query di ricerca come una semplice stringa di­ret­ta­men­te nella query di ricerca:

GET bibliography/novels/_search?q=atwood

Potete anche ricercare soltanto all’interno di un de­ter­mi­na­to campo:

GET bibliography/novels/_search?q=author:atwood
Fatto

Di fatto anche nel primo esempio cercate in un campo preciso senza doverlo spe­ci­fi­ca­re: il campo _all. Quando si incolla il contenuto di un documento in campi ordinati nell’indice, Ela­stic­search crea un campo ag­giun­ti­vo in back­ground. In questo tutti i contenuti degli altri campi vengono inoltre me­mo­riz­za­ti per con­sen­ti­re tale ricerca in tutti i campi.

Se volete combinare più criteri di ricerca, usate +. Con il segno – escludete de­ter­mi­na­ti criteri. Tuttavia se si uti­liz­za­no questi operatori, è ne­ces­sa­rio applicare la codifica per­cen­tua­le nella query di ricerca:

GET bibliography/novels/_search?q=%2Bauthor%3Aatwood+%2Btitle%3Ahandmaid

La sintassi della stringa di query di Ela­stic­search offre ancora più sot­ti­gliez­ze per per­so­na­liz­za­re la ricerca. Nella do­cu­men­ta­zio­ne del sofware gli svi­lup­pa­to­ri di Elasic hanno riassunto tutto l’es­sen­zia­le: scor­cia­to­ie OR, frasi esatte, campi vuoti o me­ta­ca­rat­te­ri.

Questa variante di ricerca è adatta per semplici query, ma per compiti più complessi il metodo Lite può fallire: il rischio di inserire un errore in una stringa lunga è molto grande. Ecco perché Ela­stic­search offre un metodo più pratico con Query DSL. Il punto di partenza per tale ricerca è il parametro di query in com­bi­na­zio­ne con una match query:

GET bibliography/novels/_search
{
	"query": {
		"match": {
"author": "allende"
}
	}
}

Il risultato mostra tutte le voci che con­ten­go­no la parola “allende” nel campo author. Ri­co­no­scia­mo che l’analisi ha fun­zio­na­to nella mappatura perché Ela­stic­search ignora le lettere maiuscole e minuscole. Per vi­sua­liz­za­re tutte le voci potete anche uti­liz­za­re match_all in aggiunta alla variante semplice già pre­sen­ta­ta:

GET bibliography/novels/_search
{
	"query": {
		"match_all": {}
	}
}

Il contrario di questa ricerca è match_none. Ela­stic­search vi dà anche la pos­si­bi­li­tà di cercare un solo termine di ricerca in più campi con­tem­po­ra­nea­men­te:

GET bibliography/novels/_search
{
	"query": {
		"multi_match": {
			"query": "la",
			"fields": ["author", "title"]
		}
	}
}

Per con­sen­ti­re ordini di ricerca complessi potete combinare anche diversi termini di ricerca e valutarli in modo diverso. Avete a di­spo­si­zio­ne tre modalità di vincolo:

  • must: il termine deve ve­ri­fi­car­si.
  • must_not: il termine non può ve­ri­fi­car­si.
  • should: se compare questo termine, aumenta la per­ti­nen­za nei risultati della ricerca.

Nella pratica le com­bi­ne­re­te con una query booleana:

GET bibliography/novels/search_
{
	"query": {
"bool": {
		"must": {
			"match": {
				"title": "la"
			}
},
		"must_not": {
			"match": {
				"title": "rabbit"
			}
		},
		"should": {
			"match": {
				"author": "allende"
			}
		}
	}
}
}

Potete inoltre espandere la vostra ricerca in­stal­lan­do un filtro. Ciò consente di impostare criteri che limitano i risultati della ricerca:

{
	"query": {
"bool": {
		"must": {
			"match": {
				"title": "la"
			}
},
		"filter": {
			"range": {
				"year": {
					"gte": "1950",
					"lt": "2000"
				}
			}
		}
	}
}
}

Nell’esempio pre­ce­den­te abbiamo collegato il filtro a uno spettro di valori: dovevano essere vi­sua­liz­za­te soltanto le voci comprese tra il 1950 e il 2000.

In sintesi

Con questo strumento avete a di­spo­si­zio­ne tutto quello che vi serve per im­ple­men­ta­re la ricerca full text nel vostro progetto. Ela­stic­search, tuttavia, offre altri metodi che possono affinare la ricerca e renderla più complessa. Sul sito ufficiale di Elastic si possono trovare maggiori in­for­ma­zio­ni. Se volete estendere ul­te­rior­men­te la ricerca full text, potete anche creare i vostri script con altre lingue come Groovy e Clojure.

Vantaggi e svantaggi di Ela­stic­search

Ela­stic­search può essere un potente strumento di ricerca full text. L’unica pecca che si può at­tri­bui­re a Ela­stic­search è la cattiva im­ple­men­ta­zio­ne del concetto open source. Per il resto la ricerca full text offre numerosi vantaggi, anche rispetto al diretto con­cor­ren­te Apache Solr.

Vantaggi Svantaggi
Open source Elastic come Ga­te­kee­per
Veloce e stabile
Scalabile
Molti moduli di programma già pronti (analyzer, ricerca full text, ecc.)
Facile im­ple­men­ta­zio­ne grazie a Java, JSON e REST-API
Fles­si­bi­le e dinamico
Vai al menu prin­ci­pa­le