Non solo copiare da Stack Overflow ma capire cosa stai copiando.
Elasticsearch è il motore di ricerca per eccellenza in questi giorni, ma il suo DSL di query ha una ripida curva di apprendimento. Quando ho iniziato a scrivere query Elasticsearch, potevo mettere insieme qualcosa che funzionava attraverso una combinazione di documenti di Elastic.co e Stack Overflow, ma non capivo appieno i concetti sottostanti la sintassi.
Questo tutorial vuole essere quello che avrei voluto leggere per primo. Presuppone che il lettore abbia familiarità con i concetti di base di Elasticsearch, possa scrivere semplici query e comprenda la logica booleana. Ha lo scopo di fornire al lettore una solida base concettuale di Elasticsearch prima di provare a capire la sintassi.
Filtrare i valori esatti vs. ricerca analizzata a tutto testo
Un tema dominante in Elasticsearch è che tutte le query possono essere classificate in tre tipi:
1. Filtraggio per valori esatti
2. Ricerca su testo analizzato
3. Una combinazione dei due
Ogni campo del documento può essere classificato come valore esatto o testo analizzato (chiamato anche full text). I valori esatti sono campi come user_id
date
email_addresses
, ecc. Il testo analizzato è dati di testo come product_description
o email_body
. Come il nome implica, questi dati di testo sono stati analizzati (ne parleremo più avanti). È spesso in un linguaggio naturale umano, ma non necessariamente.
L’interrogazione dei documenti può essere fatta specificando i filtri sui valori esatti. In questi casi, la domanda se il documento viene restituito è un sì o un no binario. Per esempio, il user_id
del documento è uguale a 174517
? La data created_at
del documento è compresa nell’intervallo dell’ultimo mese?
D’altra parte, l’interrogazione dei documenti attraverso la ricerca del testo analizzato restituisce risultati basati sulla rilevanza. Un documento non è restituito da un criterio sì/no, ma da quanto è rilevante. Per esempio, se il testo analizzato di un documento include Johnny Depp, dovrebbe essere restituito anche nelle ricerche di John Depp o Johnnie Depp. Una ricerca per cook dovrebbe anche restituire risultati per cooking e cooked.
Da questo comportamento, possiamo dedurre che la ricerca per testo analizzato è un’operazione molto complessa e coinvolge diversi pacchetti di analizzatori a seconda del tipo di dati testuali. Per esempio, alcuni pacchetti di analizzatori sono specifici per la lingua e vengono utilizzati per analizzare il testo in una certa lingua. Il pacchetto analizzatore predefinito è l’analizzatore standard che divide il testo in base ai confini delle parole, alle lettere minuscole e rimuove la punteggiatura. Poiché la ricerca per testo analizzato è molto più complicata del filtraggio per valori esatti, è molto meno performante del semplice filtraggio per valori esatti. Nota, chiameremo la ricerca per testo analizzato come ricerca analizzata per brevità.
Il DSL delle query
Le query di Elasticsearch sono composte da una o molte clausole di query. Le clausole di query possono essere combinate per creare altre clausole di query, chiamate clausole di query composte. Tutte le clausole di query hanno uno di questi due formati:
{
QUERY_CLAUSE: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}{
QUERY_CLAUSE: {
FIELD_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
}
La regola della sintassi è che le clausole di query possono essere ripetutamente annidate dentro altre clausole di query
{
QUERY_CLAUSE {
QUERY_CLAUSE: {
QUERY_CLAUSE: {
QUERY_CLAUSE: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
}
}
}
Queste sono alcune clausole di query comuni.
Clausola di query match
La clausola di query match è la più generica e comunemente usata. È abbastanza intelligente in quanto quando viene eseguita su un campo di testo analizzato, esegue una ricerca analizzata sul testo. Quando viene eseguita su un campo di valore esatto, esegue un filtro.
Nell’esempio qui sotto, la prima clausola di query eseguirà una ricerca analizzata poiché description
è un campo di testo analizzato. Mentre le seconde 2 query sono filtri su campi di valore esatto.
{ "match": { "description": "Fourier analysis signals processing" }}
{ "match": { "date": "2014-09-01" }}
{ "match": { "visible": true }}
La clausola match all query
La clausola match all query restituisce tutti i documenti. È analoga a SELECT * FROM table
in SQL.
{ "match_all": {} }
La clausola di query Term/Terms
Le clausole di query term e terms sono usate per filtrare un campo a valore esatto per valori singoli o multipli, rispettivamente. Nel caso di valori multipli, la connessione logica è OR
.
Per esempio, la prima query trova tutti i documenti con il tag “math”. La seconda query trova tutti i documenti con i tag “math” o “statistics”.
{ "term": { "tag": "math" }}
{ "terms": { "tag": }}
Clausola di query multi match
La clausola di query multi match è una query che viene eseguita su più campi invece che su uno solo.
{
"multi_match": {
"query": "probability theory",
"fields":
}
}
Clausola di query con filtri Exists e Missing
Il filtro exists controlla che i documenti abbiano un valore in un campo specificato. Il filtro mancante controlla che i documenti non abbiano un valore in un campo specificato. Sono analoghi alle clausole IS NULL
e IS NOT NULL
di SQL.
{
"exists" : {
"field" : "title"
}
}
e
{
"missing" : {
"field" : "title"
}
}
Clausola di query filtro range
La clausola di query filtro range è usata per filtrare i campi numero e data in range, utilizzando gli operatori gt
gte
lt
lte
breve per greater_than
greater_than_or_equal
less_than
e less_than_or_equal
, rispettivamente.
{ "range" : { "age" : { "gt" : 30 } } }{
"range": {
"born" : {
"gte": "01/01/2012",
"lte": "2013",
"format": "dd/MM/yyyy||yyyy"
}
}
}
Clausola di query composta
Le clausole di query che sono costruite da altre clausole di query sono chiamate clausole di query composte. Si noti che le clausole di query composte possono anche essere formate da altre clausole di query composte, permettendo una nidificazione a più livelli.
La clausola di query bool è un esempio di clausola di query composta, poiché è usata per combinare più clausole di query usando operatori booleani. I tre operatori booleani supportati sono must
must_not
e should
, che corrispondono rispettivamente a AND
NOT
, e OR
.
Per esempio, supponiamo di avere un indice sul posts
di un popolare sito di social media. Ecco una query per trovare tutti i posts
sulla matematica che non è probabilità, dove è o non letto o è stato favorito.
{
"bool": {
"must": { "term": { "tag": "math" }},
"must_not": { "term": { "tag": "probability" }},
"should":
}
}
Combinare la ricerca analizzata con i filtri
Abbiamo parlato di filtri per campi esatti e ricerca analizzata in contesti separati, ma nelle applicazioni del mondo reale, spesso vogliamo combinare i due. Combiniamo la ricerca analizzata e i filtri di campo esatti usando la clausola filtered.
Per esempio, supponiamo di avere un indice sul posts
di un popolare forum web sulla matematica. Ecco una query per trovare tutti i post eseguendo una ricerca analizzata per “Teoria della probabilità”, ma vogliamo solo i posts
con 20 o più voti e non quelli con il tag “frequentista”.
{
"filtered": {
"query": { "match": { "body": "Probability Theory" }},
"filter": {
"bool": {
"must": {
"range": { "upvotes" : { "gt" : 20 } }
},
"must_not": { "term": { "tag": "frequentist" } }
}
}
}
}
Summary
Lo sfondo concettuale del DSL di query Elasticsearch è questa dicotomia tra filtrare i documenti e cercare nel testo analizzato. Spero che abbiate trovato questo utile.