Introduzione rapida alla ricerca full-text con ElasticSearch

Persistenza in alto

Ho appena annunciato il nuovo corso Learn Spring , incentrato sui fondamenti di Spring 5 e Spring Boot 2:

>> SCOPRI IL CORSO

1. Panoramica

Esegue query di ricerca full-text ed esegue ricerche linguistiche sui documenti. Include parole o frasi singole o multiple e restituisce documenti che corrispondono alla condizione di ricerca.

ElasticSearch è un motore di ricerca basato su Apache Lucene, una libreria di software per il recupero delle informazioni gratuito e open source. Fornisce un motore di ricerca full-text distribuito con un'interfaccia web HTTP e documenti JSON senza schema.

Questo articolo esamina l'API REST di ElasticSearch e illustra le operazioni di base utilizzando solo richieste HTTP.

2. Configurazione

Per installare ElasticSearch sulla tua macchina, fai riferimento alla guida di installazione ufficiale.

L'API RESTfull viene eseguita sulla porta 9200. Testiamo se funziona correttamente utilizzando il seguente comando curl:

curl -XGET '//localhost:9200/'

Se osservi la seguente risposta, l'istanza è in esecuzione correttamente:

{ "name": "NaIlQWU", "cluster_name": "elasticsearch", "cluster_uuid": "enkBkWqqQrS0vp_NXmjQMQ", "version": { "number": "5.1.2", "build_hash": "c8c4c16", "build_date": "2017-01-11T20:18:39.146Z", "build_snapshot": false, "lucene_version": "6.3.0" }, "tagline": "You Know, for Search" }

3. Indicizzazione dei documenti

ElasticSearch è orientato ai documenti. Memorizza e indicizza i documenti. L'indicizzazione crea o aggiorna i documenti. Dopo l'indicizzazione, è possibile cercare, ordinare e filtrare documenti completi, non righe di dati a colonne. Questo è un modo fondamentalmente diverso di pensare ai dati ed è uno dei motivi per cui ElasticSearch può eseguire una ricerca full-text complessa.

I documenti sono rappresentati come oggetti JSON. La serializzazione JSON è supportata dalla maggior parte dei linguaggi di programmazione ed è diventato il formato standard utilizzato dal movimento NoSQL. È semplice, conciso e di facile lettura.

Utilizzeremo le seguenti voci casuali per eseguire la nostra ricerca nel testo completo:

{ "title": "He went", "random_text": "He went such dare good fact. The small own seven saved man age." } { "title": "He oppose", "random_text": "He oppose at thrown desire of no. \ Announcing impression unaffected day his are unreserved indulgence." } { "title": "Repulsive questions", "random_text": "Repulsive questions contented him few extensive supported." } { "title": "Old education", "random_text": "Old education him departure any arranging one prevailed." }

Prima di poter indicizzare un documento, dobbiamo decidere dove archiviarlo. È possibile avere più indici, che a loro volta contengono più tipi. Questi tipi contengono più documenti e ogni documento ha più campi.

Memorizzeremo i nostri documenti utilizzando il seguente schema:

text : il nome dell'indice.

articolo : il nome del tipo.

id : l'ID di questo particolare esempio di immissione di testo.

Per aggiungere un documento eseguiremo il seguente comando:

curl -XPUT 'localhost:9200/text/article/1?pretty' -H 'Content-Type: application/json' -d ' { "title": "He went", "random_text": "He went such dare good fact. The small own seven saved man age." }'

Qui stiamo usando id = 1 , possiamo aggiungere altre voci usando lo stesso comando e id incrementato.

4. Recupero di documenti

Dopo aver aggiunto tutti i nostri documenti possiamo controllare quanti documenti, utilizzando il seguente comando, abbiamo nel cluster:

curl -XGET '//localhost:9200/_count?pretty' -d ' { "query": { "match_all": {} } }' 

Inoltre, possiamo ottenere un documento usando il suo id con il seguente comando:

curl -XGET 'localhost:9200/text/article/1?pretty' 

E dovremmo ottenere la seguente risposta dalla ricerca elastica:

{ "_index": "text", "_type": "article", "_id": "1", "_version": 1, "found": true, "_source": { "title": "He went", "random_text": "He went such dare good fact. The small own seven saved man age." } }

Come possiamo vedere questa risposta corrisponde alla voce aggiunta utilizzando l'id 1.

5. Interrogazione di documenti

OK eseguiamo una ricerca full-text con il seguente comando:

curl -XGET 'localhost:9200/text/article/_search?pretty' -H 'Content-Type: application/json' -d ' { "query": { "match": { "random_text": "him departure" } } }'

E otteniamo il seguente risultato:

{ "took": 32, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 2, "max_score": 1.4513469, "hits": [ { "_index": "text", "_type": "article", "_id": "4", "_score": 1.4513469, "_source": { "title": "Old education", "random_text": "Old education him departure any arranging one prevailed." } }, { "_index": "text", "_type": "article", "_id": "3", "_score": 0.28582606, "_source": { "title": "Repulsive questions", "random_text": "Repulsive questions contented him few extensive supported." } } ] } }

Come si vede si cerca “lui partenza” e si ottengono due risultati con punteggi differenti. Il primo risultato è ovvio perché il testo ha al suo interno la ricerca eseguita e come possiamo vedere abbiamo il punteggio di 1.4513469 .

Il secondo risultato viene recuperato perché il documento di destinazione contiene la parola "lui".

Per impostazione predefinita, ElasticSearch ordina i risultati corrispondenti in base al loro punteggio di pertinenza, ovvero in base a quanto ogni documento corrisponde alla query. Nota che il punteggio del secondo risultato è piccolo rispetto al primo risultato, indicando una rilevanza inferiore.

6. Ricerca fuzzy

La corrispondenza fuzzy tratta due parole "sfocate" simili come se fossero la stessa parola. Innanzitutto, dobbiamo definire cosa intendiamo per sfocatura.

Elasticsearch supporta una distanza di modifica massima, specificata con il parametro fuzziness, di 2. Il parametro fuzziness può essere impostato su AUTO, il che si traduce nelle seguenti distanze di modifica massime:

  • 0 per stringhe di uno o due caratteri
  • 1 per stringhe di tre, quattro o cinque caratteri
  • 2 per stringhe di più di cinque caratteri

you may find that an edit distance of 2 returns results that don’t appear to be related.

You may get better results, and better performance, with a maximum fuzziness of 1. Distance refers to the Levenshtein distance that is a string metric for measuring the difference between two sequences. Informally, the Levenshtein distance between two words is the minimum number of single-character edits.

OK let's perform our search with fuzziness:

curl -XGET 'localhost:9200/text/article/_search?pretty' -H 'Content-Type: application/json' -d' { "query": { "match": { "random_text": { "query": "him departure", "fuzziness": "2" } } } }'

And here's the result:

{ "took": 88, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 4, "max_score": 1.5834423, "hits": [ { "_index": "text", "_type": "article", "_id": "4", "_score": 1.4513469, "_source": { "title": "Old education", "random_text": "Old education him departure any arranging one prevailed." } }, { "_index": "text", "_type": "article", "_id": "2", "_score": 0.41093433, "_source": { "title": "He oppose", "random_text": "He oppose at thrown desire of no. \ Announcing impression unaffected day his are unreserved indulgence." } }, { "_index": "text", "_type": "article", "_id": "3", "_score": 0.2876821, "_source": { "title": "Repulsive questions", "random_text": "Repulsive questions contented him few extensive supported." } }, { "_index": "text", "_type": "article", "_id": "1", "_score": 0.0, "_source": { "title": "He went", "random_text": "He went such dare good fact. The small own seven saved man age." } } ] } }'

As we can see the fuzziness give us more results.

We need to use fuzziness carefully because it tends to retrieve results that look unrelated.

7. Conclusion

In this quick tutorial we focused on indexing documents and querying Elasticsearch for full-text search, directly via it's REST API.

Ovviamente, abbiamo API disponibili per più linguaggi di programmazione quando ne abbiamo bisogno, ma l'API è ancora abbastanza comoda e indipendente dal linguaggio.

Fondo di persistenza

Ho appena annunciato il nuovo corso Learn Spring , incentrato sui fondamenti di Spring 5 e Spring Boot 2:

>> SCOPRI IL CORSO