Nozioni di base su Elasticsearch

Elasticsearch Γ¨ un motore di ricerca con json rest api, che utilizza Lucene e scritto in Java. Una descrizione di tutti i vantaggi di questo motore Γ¨ disponibile su il sito ufficiale. Nel seguito faremo riferimento ad Elasticsearch come ES.

Motori simili vengono utilizzati per ricerche complesse in un database di documenti. Ad esempio, la ricerca tenendo conto della morfologia della lingua o la ricerca per coordinate geografiche.

In questo articolo parlerΓ² delle basi di ES utilizzando l'esempio dell'indicizzazione dei post del blog. Ti mostrerΓ² come filtrare, ordinare e cercare documenti.

Per non dipendere dal sistema operativo, farΓ² tutte le richieste a ES utilizzando CURL. Esiste anche un plugin per Google Chrome chiamato senso.

Il testo contiene collegamenti a documentazione e altre fonti. Alla fine sono presenti i link per un rapido accesso alla documentazione. Le definizioni dei termini non familiari si trovano in лоссарии.

Installazione dell'ES

Per fare ciΓ², abbiamo prima bisogno di Java. Sviluppatori Raccomandare installare le versioni Java piΓΉ recenti di Java 8 aggiornamento 20 o Java 7 aggiornamento 55.

La distribuzione ES Γ¨ disponibile su sito dello sviluppatore. Dopo aver decompresso l'archivio Γ¨ necessario eseguire bin/elasticsearch. Anche disponibile pacchetti per apt e yum. C'Γ¨ immagine ufficiale per la finestra mobile. Ulteriori informazioni sull'installazione.

Dopo l'installazione e l'avvio, controlliamo la funzionalitΓ :

# для удобства Π·Π°ΠΏΠΎΠΌΠ½ΠΈΠΌ адрСс Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ
#export ES_URL=$(docker-machine ip dev):9200
export ES_URL=localhost:9200

curl -X GET $ES_URL

Riceveremo qualcosa del genere:

{
  "name" : "Heimdall",
  "cluster_name" : "elasticsearch",
  "version" : {
    "number" : "2.2.1",
    "build_hash" : "d045fc29d1932bce18b2e65ab8b297fbf6cd41a1",
    "build_timestamp" : "2016-03-09T09:38:54Z",
    "build_snapshot" : false,
    "lucene_version" : "5.4.1"
  },
  "tagline" : "You Know, for Search"
}

indicizzazione

Aggiungiamo un post a ES:

# Π”ΠΎΠ±Π°Π²ΠΈΠΌ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ c id 1 Ρ‚ΠΈΠΏΠ° post Π² индСкс blog.
# ?pretty ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Π²Ρ‹Π²ΠΎΠ΄ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ Ρ‡Π΅Π»ΠΎΠ²Π΅ΠΊΠΎ-Ρ‡ΠΈΡ‚Π°Π΅ΠΌΡ‹ΠΌ.

curl -XPUT "$ES_URL/blog/post/1?pretty" -d'
{
  "title": "ВСсСлыС котята",
  "content": "<p>БмСшная история ΠΏΡ€ΠΎ котят<p>",
  "tags": [
    "котята",
    "смСшная история"
  ],
  "published_at": "2014-09-12T20:44:42+00:00"
}'

risposta del server:

{
  "_index" : "blog",
  "_type" : "post",
  "_id" : "1",
  "_version" : 1,
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "created" : false
}

ES creato automaticamente indice blog e Ρ‚ΠΈΠΏ inviare. Possiamo tracciare un'analogia condizionale: un indice Γ¨ un database e un tipo Γ¨ una tabella in questo database. Ogni tipo ha il proprio schema βˆ’ mappatura, proprio come una tabella relazionale. La mappatura viene generata automaticamente quando il documento viene indicizzato:

# ΠŸΠΎΠ»ΡƒΡ‡ΠΈΠΌ mapping всСх Ρ‚ΠΈΠΏΠΎΠ² индСкса blog
curl -XGET "$ES_URL/blog/_mapping?pretty"

Nella risposta del server ho aggiunto nei commenti i valori dei campi del documento indicizzato:

{
  "blog" : {
    "mappings" : {
      "post" : {
        "properties" : {
          /* "content": "<p>БмСшная история ΠΏΡ€ΠΎ котят<p>", */ 
          "content" : {
            "type" : "string"
          },
          /* "published_at": "2014-09-12T20:44:42+00:00" */
          "published_at" : {
            "type" : "date",
            "format" : "strict_date_optional_time||epoch_millis"
          },
          /* "tags": ["котята", "смСшная история"] */
          "tags" : {
            "type" : "string"
          },
          /*  "title": "ВСсСлыС котята" */
          "title" : {
            "type" : "string"
          }
        }
      }
    }
  }
}

Vale la pena notare che ES non distingue tra un singolo valore e un array di valori. Ad esempio, il campo title contiene semplicemente un titolo e il campo tags contiene un array di stringhe, sebbene siano rappresentate allo stesso modo nella mappatura.
Parleremo piΓΉ approfonditamente della mappatura in seguito.

richieste

Recupero di un documento tramite il suo ID:

# ΠΈΠ·Π²Π»Π΅Ρ‡Π΅ΠΌ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ с id 1 Ρ‚ΠΈΠΏΠ° post ΠΈΠ· индСкса blog
curl -XGET "$ES_URL/blog/post/1?pretty"
{
  "_index" : "blog",
  "_type" : "post",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "_source" : {
    "title" : "ВСсСлыС котята",
    "content" : "<p>БмСшная история ΠΏΡ€ΠΎ котят<p>",
    "tags" : [ "котята", "смСшная история" ],
    "published_at" : "2014-09-12T20:44:42+00:00"
  }
}

Nella risposta sono apparse nuove chiavi: _version ΠΈ _source. In generale, tutte le chiavi iniziano con _ sono classificati come ufficiali.

Chiave _version mostra la versione del documento. È necessario affinché il meccanismo di blocco ottimistico funzioni. Ad esempio, vogliamo modificare un documento che ha la versione 1. Inviamo il documento modificato e indichiamo che si tratta di una modifica di un documento con la versione 1. Se anche qualcun altro ha modificato un documento con la versione 1 e ha inviato le modifiche prima di noi, allora ES non accetterà le nostre modifiche, perché memorizza il documento con la versione 2.

Chiave _source contiene il documento che abbiamo indicizzato. ES non utilizza questo valore per le operazioni di ricerca perchΓ© Gli indici vengono utilizzati per la ricerca. Per risparmiare spazio, ES memorizza un documento sorgente compresso. Se abbiamo bisogno solo dell'ID e non dell'intero documento sorgente, possiamo disabilitare l'archiviazione del sorgente.

Se non abbiamo bisogno di informazioni aggiuntive, possiamo ottenere solo il contenuto di _source:

curl -XGET "$ES_URL/blog/post/1/_source?pretty"
{
  "title" : "ВСсСлыС котята",
  "content" : "<p>БмСшная история ΠΏΡ€ΠΎ котят<p>",
  "tags" : [ "котята", "смСшная история" ],
  "published_at" : "2014-09-12T20:44:42+00:00"
}

Puoi anche selezionare solo alcuni campi:

# ΠΈΠ·Π²Π»Π΅Ρ‡Π΅ΠΌ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎΠ»Π΅ title
curl -XGET "$ES_URL/blog/post/1?_source=title&pretty"
{
  "_index" : "blog",
  "_type" : "post",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "_source" : {
    "title" : "ВСсСлыС котята"
  }
}

Indicizziamo qualche altro post ed eseguiamo query piΓΉ complesse.

curl -XPUT "$ES_URL/blog/post/2" -d'
{
  "title": "ВСсСлыС Ρ‰Π΅Π½ΠΊΠΈ",
  "content": "<p>БмСшная история ΠΏΡ€ΠΎ Ρ‰Π΅Π½ΠΊΠΎΠ²<p>",
  "tags": [
    "Ρ‰Π΅Π½ΠΊΠΈ",
    "смСшная история"
  ],
  "published_at": "2014-08-12T20:44:42+00:00"
}'
curl -XPUT "$ES_URL/blog/post/3" -d'
{
  "title": "Как Ρƒ мСня появился ΠΊΠΎΡ‚Π΅Π½ΠΎΠΊ",
  "content": "<p>Π”ΡƒΡˆΠ΅Ρ€Π°Π·Π΄ΠΈΡ€Π°ΡŽΡ‰Π°Ρ история ΠΏΡ€ΠΎ Π±Π΅Π΄Π½ΠΎΠ³ΠΎ ΠΊΠΎΡ‚Π΅Π½ΠΊΠ° с ΡƒΠ»ΠΈΡ†Ρ‹<p>",
  "tags": [
    "котята"
  ],
  "published_at": "2014-07-21T20:44:42+00:00"
}'

Ordinamento

# Π½Π°ΠΉΠ΄Π΅ΠΌ послСдний пост ΠΏΠΎ Π΄Π°Ρ‚Π΅ ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ ΠΈ ΠΈΠ·Π²Π»Π΅Ρ‡Π΅ΠΌ поля title ΠΈ published_at
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
  "size": 1,
  "_source": ["title", "published_at"],
  "sort": [{"published_at": "desc"}]
}'
{
  "took" : 8,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 3,
    "max_score" : null,
    "hits" : [ {
      "_index" : "blog",
      "_type" : "post",
      "_id" : "1",
      "_score" : null,
      "_source" : {
        "title" : "ВСсСлыС котята",
        "published_at" : "2014-09-12T20:44:42+00:00"
      },
      "sort" : [ 1410554682000 ]
    } ]
  }
}

Abbiamo scelto l'ultimo post. size limita il numero di documenti da rilasciare. total mostra il numero totale di documenti corrispondenti alla richiesta. sort nell'output contiene un array di numeri interi in base al quale viene eseguito l'ordinamento. Quelli. la data Γ¨ stata convertita in un numero intero. Maggiori informazioni sull'ordinamento possono essere trovate in documentazione.

Filtri e query

ES a partire dalla versione 2 non distingue invece tra filtri e query viene introdotto il concetto di contesto.
Un contesto di query differisce da un contesto di filtro in quanto la query genera un _score e non viene memorizzata nella cache. Ti mostrerΓ² cos'Γ¨ _score piΓΉ tardi.

Filtra per data

Usiamo la richiesta gamma nel contesto del filtro:

# ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ посты, ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Π½Π½Ρ‹Π΅ 1ΠΎΠ³ΠΎ сСнтября ΠΈΠ»ΠΈ ΠΏΠΎΠ·ΠΆΠ΅
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
  "filter": {
    "range": {
      "published_at": { "gte": "2014-09-01" }
    }
  }
}'

Filtra per tag

Noi usiamo interrogazione sui termini per cercare gli ID dei documenti contenenti una determinata parola:

# Π½Π°ΠΉΠ΄Π΅ΠΌ всС Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Ρ‹, Π² ΠΏΠΎΠ»Π΅ tags ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π΅ΡΡ‚ΡŒ элСмСнт 'котята'
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
  "_source": [
    "title",
    "tags"
  ],
  "filter": {
    "term": {
      "tags": "котята"
    }
  }
}'
{
  "took" : 9,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 1.0,
    "hits" : [ {
      "_index" : "blog",
      "_type" : "post",
      "_id" : "1",
      "_score" : 1.0,
      "_source" : {
        "title" : "ВСсСлыС котята",
        "tags" : [ "котята", "смСшная история" ]
      }
    }, {
      "_index" : "blog",
      "_type" : "post",
      "_id" : "3",
      "_score" : 1.0,
      "_source" : {
        "title" : "Как Ρƒ мСня появился ΠΊΠΎΡ‚Π΅Π½ΠΎΠΊ",
        "tags" : [ "котята" ]
      }
    } ]
  }
}

Ricerca a testo integrale

Tre dei nostri documenti contengono quanto segue nel campo del contenuto:

  • <p>БмСшная история ΠΏΡ€ΠΎ котят<p>
  • <p>БмСшная история ΠΏΡ€ΠΎ Ρ‰Π΅Π½ΠΊΠΎΠ²<p>
  • <p>Π”ΡƒΡˆΠ΅Ρ€Π°Π·Π΄ΠΈΡ€Π°ΡŽΡ‰Π°Ρ история ΠΏΡ€ΠΎ Π±Π΅Π΄Π½ΠΎΠ³ΠΎ ΠΊΠΎΡ‚Π΅Π½ΠΊΠ° с ΡƒΠ»ΠΈΡ†Ρ‹<p>

Noi usiamo domanda di corrispondenza per cercare gli ID dei documenti contenenti una determinata parola:

# source: false ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ ΠΈΠ·Π²Π»Π΅ΠΊΠ°Ρ‚ΡŒ _source Π½Π°ΠΉΠ΄Π΅Π½Π½Ρ‹Ρ… Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ΠΎΠ²
curl -XGET "$ES_URL/blog/post/_search?pretty" -d'
{
  "_source": false,
  "query": {
    "match": {
      "content": "история"
    }
  }
}'
{
  "took" : 13,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 3,
    "max_score" : 0.11506981,
    "hits" : [ {
      "_index" : "blog",
      "_type" : "post",
      "_id" : "2",
      "_score" : 0.11506981
    }, {
      "_index" : "blog",
      "_type" : "post",
      "_id" : "1",
      "_score" : 0.11506981
    }, {
      "_index" : "blog",
      "_type" : "post",
      "_id" : "3",
      "_score" : 0.095891505
    } ]
  }
}

Se perΓ² cerchiamo β€œstorie” nel campo del contenuto, non troveremo nulla, perchΓ© L'indice contiene solo le parole originali, non le loro radici. Per effettuare una ricerca di alta qualitΓ , Γ¨ necessario configurare l'analizzatore.

Campo _score spettacoli pertinenza. Se la richiesta viene eseguita in un contesto di filtro, il valore _score sarΓ  sempre uguale a 1, il che significa una corrispondenza completa con il filtro.

Gli analizzatori

Gli analizzatori sono necessari per convertire il testo sorgente in un insieme di token.
Gli analizzatori sono costituiti da uno Gettoniera e diversi facoltativi Filtri token. Tokenizer puΓ² essere preceduto da diversi CharFilter. I tokenizzatori suddividono la stringa di origine in token, ad esempio spazi e caratteri di punteggiatura. TokenFilter puΓ² modificare token, eliminarne o aggiungerne di nuovi, ad esempio lasciare solo la radice della parola, rimuovere preposizioni, aggiungere sinonimi. CharFilter: modifica l'intera stringa sorgente, ad esempio, elimina i tag html.

ES ne ha diversi analizzatori standard. Ad esempio, un analizzatore russo.

Usiamo api e vediamo come gli analizzatori standard e russi trasformano la stringa β€œStorie divertenti sui gattini”:

# ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Π°Π½Π°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€ standard       
# ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅ΠΊΠΎΠ΄ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π½Π΅ ASCII символы
curl -XGET "$ES_URL/_analyze?pretty&analyzer=standard&text=%D0%92%D0%B5%D1%81%D0%B5%D0%BB%D1%8B%D0%B5%20%D0%B8%D1%81%D1%82%D0%BE%D1%80%D0%B8%D0%B8%20%D0%BF%D1%80%D0%BE%20%D0%BA%D0%BE%D1%82%D1%8F%D1%82"
{
  "tokens" : [ {
    "token" : "вСсСлыС",
    "start_offset" : 0,
    "end_offset" : 7,
    "type" : "<ALPHANUM>",
    "position" : 0
  }, {
    "token" : "истории",
    "start_offset" : 8,
    "end_offset" : 15,
    "type" : "<ALPHANUM>",
    "position" : 1
  }, {
    "token" : "ΠΏΡ€ΠΎ",
    "start_offset" : 16,
    "end_offset" : 19,
    "type" : "<ALPHANUM>",
    "position" : 2
  }, {
    "token" : "котят",
    "start_offset" : 20,
    "end_offset" : 25,
    "type" : "<ALPHANUM>",
    "position" : 3
  } ]
}
# ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Π°Π½Π°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€ russian
curl -XGET "$ES_URL/_analyze?pretty&analyzer=russian&text=%D0%92%D0%B5%D1%81%D0%B5%D0%BB%D1%8B%D0%B5%20%D0%B8%D1%81%D1%82%D0%BE%D1%80%D0%B8%D0%B8%20%D0%BF%D1%80%D0%BE%20%D0%BA%D0%BE%D1%82%D1%8F%D1%82"
{
  "tokens" : [ {
    "token" : "вСсСл",
    "start_offset" : 0,
    "end_offset" : 7,
    "type" : "<ALPHANUM>",
    "position" : 0
  }, {
    "token" : "истор",
    "start_offset" : 8,
    "end_offset" : 15,
    "type" : "<ALPHANUM>",
    "position" : 1
  }, {
    "token" : "ΠΊΠΎΡ‚",
    "start_offset" : 20,
    "end_offset" : 25,
    "type" : "<ALPHANUM>",
    "position" : 3
  } ]
}

L'analizzatore standard ha diviso la stringa per spazi e ha convertito tutto in minuscolo, l'analizzatore russo ha rimosso le parole non importanti, le ha convertite in minuscolo e ha lasciato la radice delle parole.

Vediamo quali Tokenizer, TokenFilters, CharFilters utilizza l'analizzatore russo:

{
  "filter": {
    "russian_stop": {
      "type":       "stop",
      "stopwords":  "_russian_"
    },
    "russian_keywords": {
      "type":       "keyword_marker",
      "keywords":   []
    },
    "russian_stemmer": {
      "type":       "stemmer",
      "language":   "russian"
    }
  },
  "analyzer": {
    "russian": {
      "tokenizer":  "standard",
      /* TokenFilters */
      "filter": [
        "lowercase",
        "russian_stop",
        "russian_keywords",
        "russian_stemmer"
      ]
      /* CharFilters ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‚ */
    }
  }
}

Descriviamo il nostro analizzatore basato sul russo, che taglierΓ  i tag html. Chiamiamolo predefinito, perchΓ© per impostazione predefinita verrΓ  utilizzato un analizzatore con questo nome.

{
  "filter": {
    "ru_stop": {
      "type":       "stop",
      "stopwords":  "_russian_"
    },
    "ru_stemmer": {
      "type":       "stemmer",
      "language":   "russian"
    }
  },
  "analyzer": {
    "default": {
      /* добавляСм ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ html Ρ‚Π΅Π³ΠΎΠ² */
      "char_filter": ["html_strip"],
      "tokenizer":  "standard",
      "filter": [
        "lowercase",
        "ru_stop",
        "ru_stemmer"
      ]
    }
  }
}

Innanzitutto, tutti i tag HTML verranno rimossi dalla stringa sorgente, quindi lo standard tokenizzatore la dividerΓ  in token, i token risultanti verranno spostati in minuscolo, le parole insignificanti verranno rimosse e i token rimanenti rimarranno la radice della parola.

Creazione di un indice

Sopra abbiamo descritto l'analizzatore predefinito. Si applicherΓ  a tutti i campi stringa. Il nostro post contiene una serie di tag, quindi anche i tag verranno elaborati dall'analizzatore. PerchΓ© Cerchiamo i post in base alla corrispondenza esatta con un tag, quindi dobbiamo disabilitare l'analisi per il campo dei tag.

Creiamo un indice blog2 con analizzatore e mappatura, in cui l'analisi del campo tag Γ¨ disabilitata:

curl -XPOST "$ES_URL/blog2" -d'
{
  "settings": {
    "analysis": {
      "filter": {
        "ru_stop": {
          "type": "stop",
          "stopwords": "_russian_"
        },
        "ru_stemmer": {
          "type": "stemmer",
          "language": "russian"
        }
      },
      "analyzer": {
        "default": {
          "char_filter": [
            "html_strip"
          ],
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "ru_stop",
            "ru_stemmer"
          ]
        }
      }
    }
  },
  "mappings": {
    "post": {
      "properties": {
        "content": {
          "type": "string"
        },
        "published_at": {
          "type": "date"
        },
        "tags": {
          "type": "string",
          "index": "not_analyzed"
        },
        "title": {
          "type": "string"
        }
      }
    }
  }
}'

Aggiungiamo gli stessi 3 post a questo indice (blog2). OmetterΓ² questo processo perchΓ©... Γ¨ simile all'aggiunta di documenti all'indice del blog.

Ricerca di testo completo con supporto delle espressioni

Diamo un'occhiata ad un altro tipo di richiesta:

# Π½Π°ΠΉΠ΄Π΅ΠΌ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Ρ‹, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… встрСчаСтся слово 'истории'
# query -> simple_query_string -> query содСрТит поисковый запрос
# ΠΏΠΎΠ»Π΅ title ΠΈΠΌΠ΅Π΅Ρ‚ ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ 3
# ΠΏΠΎΠ»Π΅ tags ΠΈΠΌΠ΅Π΅Ρ‚ ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ 2
# ΠΏΠΎΠ»Π΅ content ΠΈΠΌΠ΅Π΅Ρ‚ ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ 1
# ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΏΡ€ΠΈ Ρ€Π°Π½ΠΆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ²
curl -XPOST "$ES_URL/blog2/post/_search?pretty" -d'
{
  "query": {
    "simple_query_string": {
      "query": "истории",
      "fields": [
        "title^3",
        "tags^2",
        "content"
      ]
    }
  }
}'

PerchΓ© Stiamo utilizzando un analizzatore con radice russa, quindi questa richiesta restituirΓ  tutti i documenti, sebbene contengano solo la parola "storia".

La richiesta puΓ² contenere caratteri speciali, ad esempio:

""fried eggs" +(eggplant | potato) -frittata"

Richiedi sintassi:

+ signifies AND operation
| signifies OR operation
- negates a single token
" wraps a number of tokens to signify a phrase for searching
* at the end of a term signifies a prefix query
( and ) signify precedence
~N after a word signifies edit distance (fuzziness)
~N after a phrase signifies slop amount
# Π½Π°ΠΉΠ΄Π΅ΠΌ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Ρ‹ Π±Π΅Π· слова 'Ρ‰Π΅Π½ΠΊΠΈ'
curl -XPOST "$ES_URL/blog2/post/_search?pretty" -d'
{
  "query": {
    "simple_query_string": {
      "query": "-Ρ‰Π΅Π½ΠΊΠΈ",
      "fields": [
        "title^3",
        "tags^2",
        "content"
      ]
    }
  }
}'

# ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ 2 поста ΠΏΡ€ΠΎ ΠΊΠΎΡ‚ΠΈΠΊΠΎΠ²

riferimenti

PS

Se sei interessato ad articoli-lezioni simili, hai idee per nuovi articoli o hai proposte di cooperazione, allora sarΓ² felice di ricevere un messaggio in un messaggio personale o via e-mail [email protected].

Fonte: habr.com