Elasticsearch: query compound

Elasticsearch offre uno strumento molto valido per effettuare ricerche semplici ma anche complesse. In questo articolo capiremo come inserire più condizioni nella stessa query e modificare il calcolo dello score in base a funzioni personalizzate e ad i valori dei dati.

Share

Reading time: 11 minutes

Negli articoli Elasticsearch: uso delle match queryElasticsearch: uso delle term query abbiamo visto come interrogare sia i campi testuali che i dati strutturati salvati all’interno di un indice di Elasticsearch. Le query utilizzate sono relativamente semplici, ma permettono di estrarre i dati di interesse ed effettuando ricerche testuali più raffinate rispetto agli standard che un database relazionale permette. Spesso, nei casi reali, abbiamo però bisogno di verificare più condizioni contemporaneamente. Inoltre, potrebbe essere necessario modificare i parametri del calcolo dello score delle query o cambiare il comportamento delle singole query. Le compound query sono interrogazioni che ci aiutano a realizzare gli scenari appena descritti. In questo articolo esamineremo alcune delle compound query più utili.

Come nei tutorial precedenti, useremo gli stessi dati sugli impiegati. Pertanto, vi consigliamo di leggere attentamente le istruzioni per installare lo stack di Elasticsearch sul vostro PC mediante il repository Docker e importare correttamente i dati.

Di seguito riportiamo i principali esempi di query trattati in questa guida, per un rapido riferimento:

Categoria Tipo Criterio di match Query Match No Match
bool compound Per applicare una combinazione di query e operatori logici must, key1:"search" 1. search will be better 1. search better for silk
should, key2:"better" 2. search will be there 2. search for silk
must_not, key3:"silk"
function_score: weight compound Assegna punteggi più alti per pesi maggiori search clause1 - weight 50 I documenti con la clausola di ricerca 1 ottiene un punteggio più alto di quello dei documenti corrispondenti alla clausola di ricerca 2 N/A
search clause 2 - weight 25
function_score: script_score compound Modifica il punteggio utilizzando script personalizzati N/A N/A N/A
function_score: field_value_factor compound Modifica il punteggio in base a un campo specifico N/A N/A N/A

Bool Query

La bool query fornisce un modo per combinare più query in modo booleano. Ad esempio, se vogliamo recuperare tutti i documenti con la parola chiave “researcher” nel campo “position” e quelli che hanno più di 12 anni di esperienza, dobbiamo usare la combinazione della query match e della query range. Questo tipo di query può essere formulato utilizzando la bool query. Questa tipologia di query prevede principalmente 4 tipi di occorrenze:

must Le condizioni o le query devono essere presenti nei documenti per considerarli corrispondenti. Inoltre, questo contribuisce al il valore del punteggio. 
Ad esempio: se manteniamo la query A e la query B nella sezione must, ogni documento nel risultato soddisferebbe entrambe le query, cioè la query A E la query B
should Le condizioni/query devono corrispondere. 
Result = queryA OR queryB
filter Stessa cosa della clausola must, ma il punteggio sarà ignorato
must_not Le condizioni/query specificate non devono non devono essere presenti nei documenti. Il punteggio viene ignorato e mantenuto pari a 0, in quanto i risultati vengono ignorati.

La struttura tipica di una bool query è la seguente:

POST _search
{
  "query": {
    "bool" : {
      "must" : [],
      "filter": [],
      "must_not" : [],
      "should" : []
    }
  }
} 

Vediamo ora come utilizzare la bool query per diversi casi d’uso.

Must

Nel nostro esempio, vogliamo trovare tutti i dipendenti che hanno 12 anni o più di esperienza e che hanno anche la parola “manager” nel campo “position”. Possiamo farlo con la seguente query

POST employees/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "position": "manager"
          }
        },
        {
          "range": {
            "experience": {
              "gte": 12
            }
          }
        }
      ]
    }
  }
} 

La risposta per la query di cui sopra avrà i documenti corrispondenti a entrambe le query nell’array “must” ed è mostrata di seguito:

{
  "took": 5,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 1.7261541,
    "hits": [
      {
        "_index": "employees",
        "_id": "4",
        "_score": 1.7261541,
        "_source": {
          "id": 4,
          "name": "Alan Thomas",
          "email": "[email protected]",
          "gender": "male",
          "ip_address": "200.47.210.95",
          "date_of_birth": "11/12/1985",
          "company": "Yamaha",
          "position": "Resources Manager",
          "experience": 12,
          "country": "China",
          "phrase": "Emulation of roots heuristic coherent systems",
          "salary": 300000
        }
      },
      {
        "_index": "employees",
        "_id": "3",
        "_score": 1.6099696,
        "_source": {
          "id": 3,
          "name": "Winston Waren",
          "email": "[email protected]",
          "gender": "male",
          "ip_address": "202.37.210.94",
          "date_of_birth": "10/11/1985",
          "company": "Yozio",
          "position": "Human Resources Manager",
          "experience": 12,
          "country": "China",
          "phrase": "Versatile object-oriented emulation",
          "salary": 50616
        }
      }
    ]
  }
}
 

Filter

L’esempio precedente mostrava il parametro “must” nella query bool. Nei risultati dell’esempio precedente si può notare che i risultati avevano valori nel campo “_score”. Utilizziamo ora la stessa query, ma questa volta sostituiamo il parametro “must” con “filter”.

POST employees/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "match": {
            "position": "manager"
          }
        },
        {
          "range": {
            "experience": {
              "gte": 12
            }
          }
        }
      ]
    }
  }
} 

Il risultato ottenuto sarà il seguente.

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 0,
    "hits": [
      {
        "_index": "employees",
        "_id": "3",
        "_score": 0,
        "_source": {
          "id": 3,
          "name": "Winston Waren",
          "email": "[email protected]",
          "gender": "male",
          "ip_address": "202.37.210.94",
          "date_of_birth": "10/11/1985",
          "company": "Yozio",
          "position": "Human Resources Manager",
          "experience": 12,
          "country": "China",
          "phrase": "Versatile object-oriented emulation",
          "salary": 50616
        }
      },
      {
        "_index": "employees",
        "_id": "4",
        "_score": 0,
        "_source": {
          "id": 4,
          "name": "Alan Thomas",
          "email": "[email protected]",
          "gender": "male",
          "ip_address": "200.47.210.95",
          "date_of_birth": "11/12/1985",
          "company": "Yamaha",
          "position": "Resources Manager",
          "experience": 12,
          "country": "China",
          "phrase": "Emulation of roots heuristic coherent systems",
          "salary": 300000
        }
      }
    ]
  }
} 

Si può notare che il valore del punteggio è pari a zero per i risultati della ricerca. Questo perché quando si utilizza il contesto filter, il punteggio non viene calcolato da Elasticsearch per rendere la ricerca più veloce.

Se si utilizza una condizione must con una condizione filter, i punteggi vengono calcolati per le clausole in must, ma non vengono calcolati per il lato filter.

Should

Vediamo ora l’effetto della sezione “should” nella bool query. Aggiungiamo una clausola “should” alla query dell’esempio precedente. Questa condizione “should” deve corrispondere ai documenti che contengono il testo “versatile” nei campi “phrase” dei documenti. La query per questa condizione sarà simile a quella riportata di seguito:

POST employees/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "position": "manager"
          }
        },
        {
          "range": {
            "experience": {
              "gte": 12
            }
          }
        }
      ],
    "should": [
      {
        "match": {
          "phrase": "versatile"
        }
      }
    ]
    }
  }
} 

Ora i risultati saranno gli stessi 2 documenti ricevuti nell’esempio precedente, ma il documento con id=3, che era stato mostrato come ultimo risultato, viene mostrato come primo risultato. Questo perché la clausola nell’array “should” si verifica in quel documento e quindi il punteggio è aumentato e quindi è stato promosso come primo documento.

{
  "took": 8,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 2.8970814,
    "hits": [
      {
        "_index": "employees",
        "_id": "3",
        "_score": 2.8970814,
        "_source": {
          "id": 3,
          "name": "Winston Waren",
          "email": "[email protected]",
          "gender": "male",
          "ip_address": "202.37.210.94",
          "date_of_birth": "10/11/1985",
          "company": "Yozio",
          "position": "Human Resources Manager",
          "experience": 12,
          "country": "China",
          "phrase": "Versatile object-oriented emulation",
          "salary": 50616
        }
      },
      {
        "_index": "employees",
        "_id": "4",
        "_score": 1.7261541,
        "_source": {
          "id": 4,
          "name": "Alan Thomas",
          "email": "[email protected]",
          "gender": "male",
          "ip_address": "200.47.210.95",
          "date_of_birth": "11/12/1985",
          "company": "Yamaha",
          "position": "Resources Manager",
          "experience": 12,
          "country": "China",
          "phrase": "Emulation of roots heuristic coherent systems",
          "salary": 300000
        }
      }
    ]
  }
} 

Condizioni multiple

Un esempio reale di bool query potrebbe essere più complesso di quelli semplici riportati sopra. Che cosa succede se gli utenti vogliono ottenere i dipendenti che potrebbero appartenere alle aziende “Yamaha” o “Telane”, e che hanno il titolo di “manager” o “associate”, con uno stipendio superiore a 100.000.

La condizione di cui sopra, se abbreviata, può essere ridotta come segue

(company = Yamaha OR company = Yozio ) AND
(position = manager OR position = associate ) AND 
(salary>=100000) 

Questo può essere ottenuto utilizzando più query bool all’interno di una singola clausola must, come mostrato nella query seguente:

POST employees/_search
{
    "query": {
        "bool": {
            "must": [
              {
                "bool": {
                    "should": [{
                        "match": {
                            "company": "Talane"
                        }
                    }, {
                        "match": {
                            "company": "Yamaha"
                        }
                    }]
                }
            }, 
            {
                "bool": {
                    "should": [
                      {
                        "match": {
                            "position": "manager"
                        }
                    }, {
                        "match": {
                            "position": "Associate"
                        }
                    }
                    ]
                }
            }, {
                "bool": {
                    "must": [
                      {
                        "range": {
                          "salary": {
                            "gte": 100000
                          }
                        }
                      }
                      ]
                }
            }]
        }
    }
}
 

Boosting Query

A volte, i criteri di ricerca richiedono che alcuni risultati vengano declassati, ma non che vengano completamente eliminati dai risultati della ricerca. In questi casi, è utile potenziare la query. Vediamo un semplice esempio per dimostrarlo.

Cerchiamo tutti i dipendenti della Cina e poi declassiamo i dipendenti dell’azienda “Telane” nei risultati della ricerca. Possiamo utilizzare una query di boosting come quella riportata di seguito

POST  employees/_search
{
    "query": {
        "boosting" : {
            "positive" : {
                "match": {
                  "country": "china"
                }
            },
            "negative" : {
                 "match": {
                  "company": "Talane"
                }
            },
            "negative_boost" : 0.5
        }
    }
} 

Ora la risposta della query di cui sopra sarebbe quella riportata di seguito, dove si può vedere che il dipendente dell’azienda “Talane” è classificato all’ultimo posto e ha una differenza di 0,5 nel punteggio rispetto al risultato precedente.

{
  "took": 14,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 4,
      "relation": "eq"
    },
    "max_score": 0.10536051,
    "hits": [
      {
        "_index": "employees",
        "_id": "2",
        "_score": 0.10536051,
        "_source": {
          "id": 2,
          "name": "Othilia Cathel",
          "email": "[email protected]",
          "gender": "female",
          "ip_address": "3.164.153.228",
          "date_of_birth": "22/07/1987",
          "company": "Edgepulse",
          "position": "Structural Engineer",
          "experience": 11,
          "country": "China",
          "phrase": "Grass-roots heuristic help-desk",
          "salary": 193530
        }
      },
      {
        "_index": "employees",
        "_id": "3",
        "_score": 0.10536051,
        "_source": {
          "id": 3,
          "name": "Winston Waren",
          "email": "[email protected]",
          "gender": "male",
          "ip_address": "202.37.210.94",
          "date_of_birth": "10/11/1985",
          "company": "Yozio",
          "position": "Human Resources Manager",
          "experience": 12,
          "country": "China",
          "phrase": "Versatile object-oriented emulation",
          "salary": 50616
        }
      },
      {
        "_index": "employees",
        "_id": "4",
        "_score": 0.10536051,
        "_source": {
          "id": 4,
          "name": "Alan Thomas",
          "email": "[email protected]",
          "gender": "male",
          "ip_address": "200.47.210.95",
          "date_of_birth": "11/12/1985",
          "company": "Yamaha",
          "position": "Resources Manager",
          "experience": 12,
          "country": "China",
          "phrase": "Emulation of roots heuristic coherent systems",
          "salary": 300000
        }
      },
      {
        "_index": "employees",
        "_id": "1",
        "_score": 0.052680254,
        "_source": {
          "id": 1,
          "name": "Huntlee Dargavel",
          "email": "[email protected]",
          "gender": "male",
          "ip_address": "58.11.89.193",
          "date_of_birth": "11/09/1990",
          "company": "Talane",
          "position": "Research Associate",
          "experience": 7,
          "country": "China",
          "phrase": "Multi-channelled coherent leverage",
          "salary": 180025
        }
      }
    ]
  }
}
 

È possibile applicare qualsiasi query alle sezioni “positiva” e “negativa” della query di boosting. Ciò è utile quando è necessario applicare più condizioni a una query bool. Un esempio di query di questo tipo è riportato di seguito:

GET employees/_search
{
  "query": {
    "boosting": {
      "positive": {
        "bool": {
          "should": [
            {
              "match": {
                "country": {
                  "query": "china"
                }
              }
            },
            {
              "range": {
                "experience": {
                  "gte": 10
                }
              }
            }
          ]
        }
      },
      "negative": {
        "match": {
          "gender": "female"
        }
      },
      "negative_boost": 0.5
    }
  }
} 

Query Function Score

La query function_score consente di modificare il punteggio dei documenti restituiti da una query. La query function_score richiede una query e una o più funzioni per calcolare il punteggio. Se non vengono menzionate funzioni, la query viene eseguita normalmente.

Il caso più semplice di function score, senza alcuna funzione, è mostrato di seguito:

Caso 1: simple match query

GET   employees/_search
{
   "_source": ["position"],
    "query": {
        "match" : {
            "position" : "manager"
        }
    }
} 

Risultato

{
  "took": 6,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 0.72615415,
    "hits": [
      {
        "_index": "employees",
        "_id": "4",
        "_score": 0.72615415,
        "_source": {
          "position": "Resources Manager"
        }
      },
      {
        "_index": "employees",
        "_id": "3",
        "_score": 0.60996956,
        "_source": {
          "position": "Human Resources Manager"
        }
      }
    ]
  }
}
 

Caso 2: match query con il punteggio modificato utilizzando la funzione score

GET   employees/_search
{
   "_source": ["position"],
    "query": {
        "function_score" : {
            "query": {
   "match" : {
      "position" : "manager"
                  }
           },
    "boost": 5,
    "boost_mode" : "multiply"
    }
  }
} 

Risultato

{
  "took": 9,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 3.630771,
    "hits": [
      {
        "_index": "employees",
        "_id": "4",
        "_score": 3.630771,
        "_source": {
          "position": "Resources Manager"
        }
      },
      {
        "_index": "employees",
        "_id": "3",
        "_score": 3.0498476,
        "_source": {
          "position": "Human Resources Manager"
        }
      }
    ]
  }
} 

function_score: weight

Come detto in precedenza, possiamo usare una o più funzioni di punteggio nell’array “functions” della query “function_score”. Una delle funzioni più semplici, ma importanti, è la funzione di punteggio “weight”.

Secondo la documentazione, questa funzione consente di moltiplicare il punteggio per il peso fornito. Il peso può essere definito per ogni funzione nell’array delle funzioni (esempio precedente) e viene moltiplicato per il punteggio calcolato dalla rispettiva funzione.

Modifichiamo leggermente la query precedente per vedere come funziona. Includiamo due filtri nella parte “functions” della query. Il primo cercherà il termine “coherent” nel campo “phrase” del documento e, se trovato, aumenterà il punteggio di un peso pari a 2. La seconda clausola cercherà il termine “emulation” nel campo “phrase” e aumenterà il punteggio di un fattore pari a 10, per tali documenti. Ecco la query:

GET employees/_search
{
"_source": ["position","phrase"], 
  "query": {
    "function_score": {
      "query": {
        "match": {
          "position": "manager"
        }
      },
      "functions": [
        {
          "filter": {
            "match": {
              "phrase": "coherent"
            }
          },
          "weight": 2
        },
        {
          "filter": {
            "match": {
              "phrase": "emulation"
            }
          },
          "weight": 10
        }
      ],
      "score_mode": "multiply", 
      "boost": "5",
      "boost_mode": "multiply"
    }
  }
} 

Il risultato della query precedente è il seguente:

{
  "took": 7,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 72.61542,
    "hits": [
      {
        "_index": "employees",
        "_id": "4",
        "_score": 72.61542,
        "_source": {
          "phrase": "Emulation of roots heuristic coherent systems",
          "position": "Resources Manager"
        }
      },
      {
        "_index": "employees",
        "_id": "3",
        "_score": 30.498476,
        "_source": {
          "phrase": "Versatile object-oriented emulation",
          "position": "Human Resources Manager"
        }
      }
    ]
  }
} 

La parte della query relativa alla corrispondenza semplice sul campo della posizione ha prodotto un punteggio di 3,63 e 3,04 per i due documenti. Quando è stata applicata la prima funzione dell’array di funzioni (corrispondenza per la parola chiave “coerente”), c’è stata una sola corrispondenza, quella per il documento con id = 4.

Il punteggio attuale di questo documento è stato moltiplicato per il fattore di peso della corrispondenza “coerente”, che è 2. Ora il nuovo punteggio per il documento diventa 3,63*2 = 7,2

Successivamente, la seconda condizione (corrispondenza per “emulazione”) ha trovato riscontro per entrambi i documenti.

Quindi il punteggio attuale del documento con id=4 è 7,2*10 = 72, dove 10 è il fattore di peso per la seconda clausola.

Il documento con id=3 ha trovato riscontro solo per la seconda clausola e quindi il suo punteggio è 3,0*10=30.

function_score: script_score

Spesso capita di dover calcolare il punteggio in base a uno o più campi e per questo il meccanismo di scoring predefinito non è sufficiente. Elasticsearch mette a disposizione la funzione di punteggio “script_score” per calcolare il punteggio in base a requisiti personalizzati. Possiamo fornire uno script che restituirà il punteggio per ogni documento in base alla logica personalizzata dei campi.

Ad esempio, dobbiamo calcolare i punteggi in funzione del salario e dell’esperienza, cioè i dipendenti con il rapporto salario/esperienza più alto dovrebbero ottenere un punteggio maggiore. Possiamo usare la seguente query function_score per lo stesso scopo:

GET employees/_search
{
  "_source": [
    "name",
    "experience",
    "salary"
  ],
  "query": {
    "function_score": {
      "query": {
        "match_all": {}
      },
      "functions": [
        {
          "script_score": {
            "script": {
              "source": "(doc['salary'].value/doc['experience'].value)/1000"
            }
          }
        }
      ],
      "boost_mode": "replace"
    }
  }
} 

La parte di script precedente genererà i punteggi per i risultati della ricerca. Ad esempio, per un dipendente con stipendio = 180025 ed esperienza = 7 il punteggio generato sarà: (180025/7)/1000 = 25.

Poiché stiamo utilizzando la modalità boost_mode: replace i punteggi calcolati dallo script saranno assegnati ad ogni documento. I risultati per la query di cui sopra sono riportati di seguito:

{
  "took": 48,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 4,
      "relation": "eq"
    },
    "max_score": 25,
    "hits": [
      {
        "_index": "employees",
        "_id": "1",
        "_score": 25,
        "_source": {
          "name": "Huntlee Dargavel",
          "experience": 7,
          "salary": 180025
        }
      },
      {
        "_index": "employees",
        "_id": "4",
        "_score": 25,
        "_source": {
          "name": "Alan Thomas",
          "experience": 12,
          "salary": 300000
        }
      },
      {
        "_index": "employees",
        "_id": "2",
        "_score": 17,
        "_source": {
          "name": "Othilia Cathel",
          "experience": 11,
          "salary": 193530
        }
      },
      {
        "_index": "employees",
        "_id": "3",
        "_score": 4,
        "_source": {
          "name": "Winston Waren",
          "experience": 12,
          "salary": 50616
        }
      }
    ]
  }
} 

function_score: field_value_factor

Possiamo utilizzare un campo del documento per influenzare il punteggio, utilizzando la funzione “field_value_factor”. Si tratta per certi versi di una semplice alternativa a “script_score”. Nel nostro esempio, utilizziamo il valore del campo “esperienza” per influenzare il nostro punteggio come segue

GET employees/_search
{
  "_source": ["name","experience"], 
    "query": {
        "function_score": {
            "field_value_factor": {
                "field": "experience",      
                 "factor": 0.5,
                "modifier": "square",
                "missing": 1
            }
        }
    }
} 

Il risultato della query è riportato di seguito:

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 4,
      "relation": "eq"
    },
    "max_score": 36,
    "hits": [
      {
        "_index": "employees",
        "_id": "3",
        "_score": 36,
        "_source": {
          "name": "Winston Waren",
          "experience": 12
        }
      },
      {
        "_index": "employees",
        "_id": "4",
        "_score": 36,
        "_source": {
          "name": "Alan Thomas",
          "experience": 12
        }
      },
      {
        "_index": "employees",
        "_id": "2",
        "_score": 30.25,
        "_source": {
          "name": "Othilia Cathel",
          "experience": 11
        }
      },
      {
        "_index": "employees",
        "_id": "1",
        "_score": 12.25,
        "_source": {
          "name": "Huntlee Dargavel",
          "experience": 7
        }
      }
    ]
  }
} 

Il calcolo del punteggio per quanto sopra sarebbe il seguente:

Square of (factor*doc[experience].value) 

Per un documento con “experience” pari a 12, il punteggio sarà:

square of (0.5*12) = square of (6) = 36 

function_score: Decay Functions

Si consideri il caso d’uso della ricerca di hotel vicino a una località. Per questo caso d’uso, più l’hotel è vicino, più i risultati della ricerca sono rilevanti, ma quando è più lontano, la ricerca diventa insignificante. Oppure, per affinare ulteriormente il concetto, se l’hotel è più lontano di una distanza percorribile a piedi di 1 km dalla località, i risultati della ricerca dovrebbero mostrare un rapido declino del punteggio. Mentre quelli che si trovano nel raggio di 1 km dovrebbero ottenere un punteggio più alto.

Per questo tipo di caso d’uso, una modalità di punteggio decrescente è la scelta migliore, cioè il punteggio inizierà a decadere dal punto di interesse. A questo scopo, Elasticsearch dispone di funzioni di punteggio chiamate funzioni di decadimento. Esistono tre tipi di funzioni di decadimento: “gauss”, “lineare” e “esponenziale” o “exp”.

Prendiamo un esempio di caso d’uso dal nostro scenario. Dobbiamo assegnare un punteggio ai dipendenti in base al loro stipendio. Quelli che si avvicinano ai 200.000 e che si trovano tra i 17.000 e i 23.000 dovrebbero ottenere un punteggio più alto, mentre quelli che si trovano al di sotto e al di sopra dell’intervallo dovrebbero avere un punteggio significativamente più basso.

GET employees/_search
{
  "_source": [
    "name",
    "salary"
  ],
  "query": {
    "function_score": {
      "query": {
        "match_all": {}
      },
      "functions": [
       {
         "gauss": {
           "salary": {
             "origin": 200000,
             "scale": 30000
           }
         }
       }
      ],
      "boost_mode": "replace"
    }
  }
} 

L’origine rappresenta il punto da cui iniziare a calcolare la distanza. La scala rappresenta la distanza dall’origine, fino alla quale deve essere assegnata la priorità per il punteggio. Ci sono altri parametri opzionali che possono essere consultati nella documentazione di Elastic.

I risultati della query sono mostrati di seguito:

{
  "took": 7,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 4,
      "relation": "eq"
    },
    "max_score": 0.9682744,
    "hits": [
      {
        "_index": "employees",
        "_id": "2",
        "_score": 0.9682744,
        "_source": {
          "name": "Othilia Cathel",
          "salary": 193530
        }
      },
      {
        "_index": "employees",
        "_id": "1",
        "_score": 0.7354331,
        "_source": {
          "name": "Huntlee Dargavel",
          "salary": 180025
        }
      },
      {
        "_index": "employees",
        "_id": "4",
        "_score": 0.00045208726,
        "_source": {
          "name": "Alan Thomas",
          "salary": 300000
        }
      },
      {
        "_index": "employees",
        "_id": "3",
        "_score": 3.4350627e-8,
        "_source": {
          "name": "Winston Waren",
          "salary": 50616
        }
      }
    ]
  }
} 

More To Explore

Elasticsearch

Elasticsearch: query compound

Elasticsearch offre uno strumento molto valido per effettuare ricerche semplici ma anche complesse. In questo articolo capiremo come inserire più condizioni nella stessa query e modificare il calcolo dello score in base a funzioni personalizzate e ad i valori dei dati.

Elasticsearch

Elasticsearch: uso delle term query

Elasticsearch offre uno strumento molto valido non solo per le ricerche testuali, ma anche per i dati strutturati. In questo articolo capiremo come interrogare i campi strutturati mediante le query term. Le varie tipologie di query ci permetteranno di raffinare le ricerche per i nostri progetti futuri.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Design with MongoDB

Design with MongoDB!!!

Buy the new book that will help you to use MongoDB correctly for your applications. Available now on Amazon!