web.php5.sk

Elasticsearch mapping VI

23. apríl 2020 / Čamo

Ako by toho ešte nebolo dosť budeme musieť prabrať po analyzeroch, normalizeroch aj tokenizery.

Tokenizery

Tokenizer rozdelí reťazec na tokeny (zvyčajne na slová). Napr. whitespace tokenizer rozdelí text na tokeny vždy keĎ narazí na biely znak. Takže výraz "quick brown fox" rozdelí na tokeny Quick, brown, fox. 

Tokenizer je tiež zodpovedný za ukladanie poradie alebo pozície každého výrazu (used for phrase and word proximity queries) a offset začiatočného a koncového písmena v pôvodnom slove, ktoré výraz predstavuje (použije sa pri zvýrazňovaní).

Existuje množstvo preddefinovaných tokenizerov, ktoré sa dajú použiť v custom analyzeroch.   

Slovne orientované tokenizery

Nasledujúce tokenizery sú zvyčajne používané pre tokenizovanie fulltextu na jednotlivé slová.

Standard Tokenizer

Standard tokenizer poskytuje grammar based tokenizáciu a funguje pre väčšinu jazykov.

Príklad

PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "standard",
          "max_token_length": 5
        }
      }
    }
  }
}

POST my_index/_analyze
{
  "analyzer": "my_analyzer",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}
 

Vráti tokeny: The, 2, QUICK, Brown, Foxes, jumpe, d, over, the, lazy, dog's, bone

jumped je rozdelené na jumpe a d kôli max_token_length. Default 255.

Standard tokenizer akceptuje nasl. parametre:

  • max_token_length: Maximálna dlžka tokenu, Ak token presiahne túto dlžku, rozdelí na na dva. Default 255. Takže ak je dlžka nastavená na 5 tak sa výraz standard tokenizer rozdelí na tokeny: stand, ard, token, izer

 

Letter Tokenizer

Rozdelí text na tokeny vždy keď narazí na znak, ktorý nieje písmeno. Funguje dobre pre väčšinu europskych jazykov ale nie moc dobre pre ázijské jazyky, ktrorých slová sú neni oddelené medzerami. 

POST _analyze
{
  "tokenizer": "letter",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}

Predošlý príklad vráti tokeny: the, QUICK, Brown, Foxes, jumped, over, the, lazy, dog, s, bone

Letter tokenizer nieje konfigurovateľný parametrami.

 

Lowercase Tokenizer

Funguje ako letter tokenizer ale navyšše prevedie tokeny na lowercase. 

The letter tokenizer breaks text into terms whenever it encounters a character which is not a letter. Takako letter filter nieje vhodný pre azijské jazyky, ktoré nemusia mať slová oddelené medzerou.

POST _analyze
{
  "tokenizer": "letter",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}
Predošlý príklad vygeneruje tokeny: the, quick, brown, foxes, jumped, over, the, lazy, dog, s, bone
 
Lowercase tokenizer nieje konfigurovateľný parametrami. 

 

Whitespace Tokenizer

Rozdelí text na tokeny vždy keĎ narazí na biely znak.  

POST _analyze
{
  "tokenizer": "whitespace",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}
 

Vráti nasl. tokeny: The, QUICK, Brown-Foxes, jumped, over, the, lazy, dog's, bone.

Whitespace tokenizer akceptuje nasl. parametre:

  • max_token_length: Maximálna dlžka tokenu. Pri jej prekročení sa token rozdelí. Default je 255.
 
 

UAX_URL_EMAIL Tokenizer

uax_url_email tokenizer je ako standard_tokenizer, ktorý navyšše rozoznáva url a email adresy ako samostatné tokeny. 

The uax_url_email tokenizer is like the standard tokenizer except that it recognises URLs and email addresses as single tokens.

POST _analyze
{
  "tokenizer": "uax_url_email",
  "text": "Email me at john.smith@global-international.com"
}
 

Vráti nasl. tokeny: Email, me, at, john.smith@global-international.com

zatiaľčo standard tokenizer vráti: Email, me, at, john.smith, global, international.com

uax_url_email tokenizer akceptuje tieto parametre:

  • max_token_length: viď. vyššie
 

Ak sa nastaví max_token_length na 5:

POST my_index/_analyze
{
  "analyzer": "my_analyzer",
  "text": "john.smith@global-international.com"
}
Vráti tokenizer takýto výsledok: john, smith, globa, l, inter, natio, nal.c, om
 
 

Classic Tokenizer

Je to grammar based tokenizer, ktroý je vhodný pre anglické dokument. Tento tokenizer má metódy na rozonávanie skratiek, názvov firiem, emailových adries a domén. To ale nefunguje bezchybne a nehodí sa pre iné jazyky. 

Rozdeľuje slová na základe interpunkcie a odstraňuje interpunkciu. Pritom bodka ak nieje nasledovaná bielym znakom je považovaná za súčasť tokenu.  Rozdeľuje cez pomlčku ale ak je v tokene číslo interpretuje ho ako číslo produktu a nerozelí ho. ??? :(. emaily a domény berie ako jeden token.

POST _analyze
{
  "tokenizer": "classic",
  "text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."
}
Vráti tokeny: The, QUICK, Brown, Foxes, jumped, over, the, lazy, dog's, bone
 
Tokenizer príma parametre:
  • max_token_length: viď vyššie.

 

Thai Tokenizer

https://www.elastic.co/guide/en/elasticsearch/reference/6.8/analysis-thai-tokenizer.html

 

Partial Word Tokenizers

Tieto tokenizery rozdelia text alebo slová do malých fragmentov aby bolo možné vyhľadávať časti jednotlivých slov.

N-Gram Tokenizer

ngram toknizer najprv rozdelí text na slová keď narazí na deliace znaky a potom vygeneruje n-gram každého slova s minimálnou definovanou dlžkou.

N-gram je ako pohyblivé okno, ktoré sa pohybuje po slove a ukladá sekvencie znakov specifickej dlžky. Používa sa pre jazyky, ktoré nedelia slová medzerami alebo obsahujú dlhé zložené slová ako nemčina. 

S defaultnými nastaveniami ngram tokenizer považuje originálny text za jedentoken a vygenruje n-grams s minimálnou dlžkou 1 a max. dlžkou 2

POST _analyze
{
  "tokenizer": "ngram",
  "text": "Quick Fox"
}

Vygeneruje toto: Q, Qu, u, ui, i, ic, c, ck, k, "k ", " ", " F", F, Fo, o, ox, x

Tokenizer príma parametre:

  • min_gram: Minimálna dĺžky gramu. Default je 1
  • max_gram: Maximána dĺžka gramu. Default je 2
  • token_chars: Skupiny znakov, ktorá bude zahrnutá do tokenov. Default [] to znamená že všetky znaky budú zahrnuté do tokenov. Skupiny znakov sú nasledovné:
    letter: napr. a, bï or 
    digit: 1, 2, ....
    whitespace: \n, \t, " "
    punctation: !, ", : ...
    symbol: &, $, ...

Zvyčajne dáva zmysel, nastaviť min a max_gram na rovnakú hodnotu. Malé hodnoty zachytia síce veľa dokumentov ale nemajú dobrú výpovednú hodnotu. min_gram 3 je dobrý základ

 

Na úrovni indexu je možné nastaviť voľbu index.max_ngram_diff ktorá obmedzuje maximálny povolený rozdiel medzi max_gram and min_gram.

{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "ngram",
          "min_gram": 3,
          "max_gram": 3,
          "token_chars": [
            "letter",
            "digit"
          ]
        }
      }
    }
  }
}

POST my_index/_analyze
{
  "analyzer": "my_analyzer",
  "text": "2 Quick Foxes."
}

Príklad vráti tokeny (číslo 2 nespadá do nin_gram): Qui, uic, ick, Fox, oxe, xes

 

Edge N-Gram Tokenizer

Tokenizer edge_ngram najprv rozdelí text na slová podľa daných znakov, potom vygeneruje n-gram pre každé slovo a pričom každý token je viazaný na začiatok slova a nepohybuje sa po slove narozdiel od n-gram tokenizeru. 

Edge n-gram tokenizer sa používa napr. pri search-as-you-type requestoch. 

Defaultne nastavenie edge n-gram tokenizera je že text berie ako jeden token a vygeneruje n-grm s min. dlžkou 1 a max. dlžkou 2 znaky. 

POST _analyze
{
  "tokenizer": "edge_ngram",
  "text": "Quick Fox"
}
Vráti: Q, Qu
 
To je skoro nepouiteľné. Preto existujú parametre cez ktoré je možno tokenizer nastaviť podľa potreby. 
 
Parametre
 
  • min_gram: minimálna dlžka gramu. Default je 1.
  • max_gram: maximálna dlžka gramu. Default je 2. Pozri Limitations of the max_gram parameter
  • token_chars: skupiny znakov ktoré budú zahrnuté do tokenov. Ostatné znaky spôsobia rozdelenie na viac tokenov. Default je [] všetky znaky
    Skupiny sú nasledovné:
    • letter:a, b, ï or 京
    • digit: 3, 7, ...
    • whitespace:  " ", "\n", ...
    • punctuation: !, ", :, ...
    • symbol: &, $, ...
Limity max_gram parametra
 
max_gram obmedzuje dlžku tokenov. Ak je hľadaný výraz dlhší ako max_gram tak Elastic nič nevráti, pretože žiadny token sa nebude zhodovať s hľadanám výrazom. 
Ak napr. max_gram je 3, hľadaný výraz apple nebude zodpovedať indexovanému výrazu app.

Dá sa tomu vyhnúť ak použijeme  truncate token filter token filter v search analyzery, ktorý skráti hľadané výrazy ma dlžku max_gram. Ak teda budem hľadať výraz apple ten sa skráti na app a taký token zaindexovaný je. Bude to ale vracať dosť nerelavantné výsledky. 

Príklad v min_gram 2 a max_gram 10

PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "edge_ngram",
          "min_gram": 2,
          "max_gram": 10,
          "token_chars": [
            "letter",
            "digit"
          ]
        }
      }
    }
  }
}

POST my_index/_analyze
{
  "analyzer": "my_analyzer",
  "text": "2 Quick Foxes."
}

Predošlý request vygeneruje tokeny: Qu, Qui, Quic, Quick, Fo, Fox, Foxe, Foxes

Zvyčajne sa odporúča použiť ten istý analyzér pri index time aj pri search time. V prípade edge-ngram tokenizeru to ale neplatí. Dáva zmysel použiť ho počas index time a počas search time je lepšie použiť standard alebo lowercase tokenzer ktorý rozelí text iba na hlavné výrazy. 

Tu je príklad ako nastaviť field pre search-as-you-type 
autocomplete analyzer indexuje tokeny qu, qui, quic, quick, fo, fox, foxe, foxes
autocomplete_search
analyzer vyhľadáva tokeny quick, fo

PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "autocomplete": {
          "tokenizer": "autocomplete",
          "filter": [
            "lowercase"
          ]
        },
        "autocomplete_search": {
          "tokenizer": "lowercase"
        }
      },
      "tokenizer": {
        "autocomplete": {
          "type": "edge_ngram",
          "min_gram": 2,
          "max_gram": 10,
          "token_chars": [
            "letter"
          ]
        }
      }
    }
  },
  "mappings": {
    "_doc": {
      "properties": {
        "title": {
          "type": "text",
          "analyzer": "autocomplete",
          "search_analyzer": "autocomplete_search"
        }
      }
    }
  }
}

PUT my_index/_doc/1
{
  "title": "Quick Foxes" 
}

POST my_index/_refresh

GET my_index/_search
{
  "query": {
    "match": {
      "title": {
        "query": "Quick Fo", 
        "operator": "and"
      }
    }
  }
}

 

Structured Text Tokenizery

Nasledujúce tokenyzery sa zvyčajne používajú v štruktúrovaných textoch ako sú identifikátory, email adresy, poštové smerovacie čísla, ... pre ktoré sa nehodí fulltexotvé indexovanie.

 

Keyword Tokenizer

Keyword tokenizer je "noop" tokenizer ktorý vkladaný text prevedie bez zmeny na jeden token. Môže byť kombinovaný s token filtrami ktoré normalizujú tokeny napr. lowercase, ...

Príklad

POST _analyze
{
  "tokenizer": "keyword",
  "text": "New York"
}
 

Vráti jeden token: "New York"

Parametre

  • buffer_size: The number of characters read into the term buffer in a single pass. Defaults to 256. The term buffer will grow by this size until all the text has been consumed. It is advisable not to change this setting.

 

Pattern Tokenizer

Pattern tokenizer používa regulárny výraz k rozdeleniu textu do tokenov, alebo aj ktorú skupinu v regulárnom výraze zahrnúť do tokoneu cez group option. 

Default pattern je \W+, kedykoľvek narazí na non-word znak.

POST _analyze
{
  "tokenizer": "pattern",
  "text": "The foo_bar_size's default is 5."
}

 Vráti: The, foo_bar_size, s, default, is, 5

Akceptuje parametre

  • pattern: Java regular expression, default je \W+.
  • flags: Java regular expression flags. Flags sa spájanú cez paipu | napr. CASE_INSENSITIVE|COMMENTS. 
  • group: Ktorú regexp. skupinu indexovať ako token. Default je -1

V nasledujúcom príklade budeme tokenizovať výrazy obalené v uvodzovkách ignorujúc vnorené escapovanú úvodzovky \". Regex vyzerá takto:

"((?:\\"|[^"]|\\")*)"

A znamená toto: 

  • Obalovacia úvodzovka "
  • Prvá zachytávaná skupina musí obsahovať buď escapovanú úvodzovku \" alebo akýkoľvek znak okrem úvodzovky [^"]
  • koncová uvodzovka "

Keďže regex vpkldáme do JSON zápisu musíme escapovať znaky \ a ". Výsledný regexp tak bude vyzerať takto:

\"((?:\\\\\"|[^\"]|\\\\\")+)\" 
PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "pattern",
          "pattern": "\"((?:\\\\\"|[^\"]|\\\\\")+)\"",
          "group": 1
        }
      }
    }
  }
}

POST my_index/_analyze
{
  "analyzer": "my_analyzer",
  "text": "\"value\", \"value with embedded \\\" quote\""
}

Request vygeneruje dva tokeny: value, value with embeded \" quote

 

Simple Pattern Tokenizer

Tokenizer používa regex, ktorý tokenizuje výrazy, ktoré tento regex zachytí. Tento model má viaceré obmedzenia v porovnaní s pattern tokenizerom, ale preto je vo výsledku rýchlejší.

Tento tokenizer nepodporuje rozdeľovanie textu na základe patternu, narozdiel od pattern tokenizeru. Na to je určený špeciálne simple_pattern_split tokenizer, ktorý sa rozoberá nižšie.

Tento tokenizer používa Lucene regular expressions + Regular Expression Syntax

Default pattern je prázny string, čo negeneruje žiadny výrazy. To znamená že simpe pattern tokenizer by mal byť vždy configurovaný s patternom.

Parametre:

 

Nasledujúci príklad generuje tokeny ktoré tvoria tri čísla.

PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "simple_pattern",
          "pattern": "[0123456789]{3}"
        }
      }
    }
  }
}

POST my_index/_analyze
{
  "analyzer": "my_analyzer",
  "text": "fd-786-335-514-x"
}
Vygeneruje tokeny: 786, 335, 514
 
 

Char Group Tokenizer

Rozloží text na tokeny vždy keď narazí na znak, ktorý je v definovanej sade znakov. Je omnoho rýchlejší ako patternové tokenizery. 
 
Parametre
  •  tokenize_on_chars: Zoznam obsahujúci zoznam znakov, cez ktoré sa bude tokenizovať. akceptuje buď jednotlivé znaky ako -, alebo skupiny znakov: whitespace, letter, digit, punctuation, symbol
POST _analyze
{
  "tokenizer": {
    "type": "char_group",
    "tokenize_on_chars": [
      "whitespace",
      "-",
      "\n"
    ]
  },
  "text": "The QUICK brown-fox"
}

Vygenruje tokeny: The, QUICK, brown, fox

 

Simple Pattern Split Tokenizer

Použije regex na rozdelenie textu do tokenov. Tokenizer nevytvára tokeny zo zachytených výrazov (narrozdieel od pattern tokenizeru), a preto je rýchlejší.  

Tento tokenizer používa Lucene regular expressions. Pre lešie pochopenie podporovaných features a syntaxe pozrite na Regular Expression Syntax

Default pattern je prázdny reťazec, ktorý vygeneruje jeden token obsahujúci celý text. Preto by mal byť vždy v konfigurácii nastavený pattern.

Parametre

Tento príklad vytvorí tokeny keď narazí na podtržítko

PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "simple_pattern_split",
          "pattern": "_"
        }
      }
    }
  }
}

POST my_index/_analyze
{
  "analyzer": "my_analyzer",
  "text": "an_underscored_phrase"
}

 

Path Hierarchy Tokenizer

Path hierarchy tokenizer príma hierarchyckú hodnotu ako napr. cestu k súboru, rozdelí ju cez path separator a vytvorí tokeny od začiatočnej časti cez všetky vnorené až po poslednú. 

Príklad na pochopenie

POST _analyze
{
  "tokenizer": "path_hierarchy",
  "text": "/one/two/three"
}
 

Vygeneruje: /one, /one/two, /one/two/three

Parametre

  • delimiter: path separator. Default je /
  • replacement: voliteľná náhrada za znak separátoru. Default je delimiter.
  • buffer_size: Počet znakov načítaných do term bufferu. Default 1024. Neodporča sa meniť.
  • reverse: ak je TRUE, generuje tokeny v obrátenom poradí. 
  • skip: počet prvých X tokenov ktoré sa vynechajú.

Príklad

PUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "path_hierarchy",
          "delimiter": "-",
          "replacement": "/",
          "skip": 2
        }
      }
    }
  }
}

POST my_index/_analyze
{
  "analyzer": "my_analyzer",
  "text": "one-two-three-four-five"
}
Vygeneruje: /three, /three/four, /three/four/five 
 
Ak chcete pridávať komentáre musíte sa prihlásiť