For AI agents: this page is also available as Markdown at /docs/text-analysis.md. Every docs page is: add .md to its URL. llms.txt lists them all.
Languages and text analysis
A text field's analyzer decides which words a document is indexed under and how a query is split, so it decides what matches. The built-in _t suffix suits English. For other languages, and for values that are not prose, such as source code, phone numbers or command lines, give the field one of the analyzers in this section in its schema.
The same analyzer runs at index time and at query time, so a query in any spelling the analyzer folds together finds the document. Prefix, wildcard and fuzzy terms get only the analyzer's normalizing steps (case, width and accent folding), not stemming or lemmatization.
#Languages
| Page | Analyzers | What it covers |
|---|---|---|
| English | the _t suffix, or snowball_english | Word splitting, case and accent folding, possessive removal and English stemming. This is the default for _t fields; see Analyzers. |
| Snowball stemming | snowball_<language> | Stemming and stop words for 30 languages, covering most European languages (German, French, Spanish, Italian, Portuguese, Dutch, the Nordic and Baltic languages, Greek, Russian and more), plus Hindi, Indonesian and Turkish. |
| Arabic | arabic | Spelling normalization, stop words and light stemming. |
| Hebrew | hebrew, hebrew_query | Dictionary lemmatization with prefix stripping and spelling without niqqud, plus exact-form matching. |
| Chinese, Japanese and Korean | cjk | Overlapping character pairs, with no dictionary. |
| Multilingual text and ICU | icu_folding, icu_normalizer, icu_transform, icu_tokenizer | Accent and case folding across scripts, Unicode normalization and transliteration. |
#Use cases
| Page | Analyzers and queries | What it covers |
|---|---|---|
| Source code | code | Identifiers, dotted paths, stack traces and log lines, matched whole and by their parts. |
| Phone numbers | phone, phone_search | Numbers matched in any format and by their trailing digits. |
| Command lines | cmdline, cmdline_exact, cmdline_base64 | Process command lines, paths, URLs and registry keys for SIEM detection, including decoded PowerShell -EncodedCommand payloads. |
| Suffix search | reverse, rwildcard | Fast leading-wildcard and suffix matches (*.exe, *\install_update.bat) on large dictionaries. |
| Substring search | trigram, substring | Exact substring, wildcard and regex matches anywhere in a value of any length, like the Elasticsearch wildcard field. |
#Use an analyzer
Name a ready-made analyzer as the field's analyzer, as a string or as {"name": ...}:
curl -X PUT https://api.warpsearch.io/v1/collections/articles \
-H "Authorization: Bearer $WARPSEARCH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"schema": {
"fields": {
"title_ar": {"type": "text", "analyzer": "arabic"},
"title_he": {"type": "text", "analyzer": "hebrew"},
"title_de": {"type": "text", "analyzer": "snowball_german"},
"title_ja": {"type": "text", "analyzer": "cjk"},
"source": {"type": "text", "analyzer": "code"},
"phone": {"type": "text", "analyzer": "phone"}
}
}
}'
Or build a chain from the components on these pages, as for any analyzer: optional char_filters, one tokenizer, then filters in order. A component with parameters is {"name": ..., "params": {...}}.
{
"type": "text",
"analyzer": {
"tokenizer": "unicode_word",
"filters": ["nfkc_cf", {"name": "snowball", "params": {"language": "german"}}]
}
}
A named analyzer combines only with char_filters, which replace the preset's own. To change anything else, write out the chain.
An analyzer cannot change once a field has data. To switch an existing field, add a new field (or a variant) with the new analyzer and reindex, or create a new collection. Search the field the usual way, for example "query": "title_de:haus" in Lucene syntax or a match query through the Elasticsearch-compatible API.
The Elasticsearch, OpenSearch and Solr compatible APIs use these analyzers too, from the analyzer names and settings those clients already send. See Through the compatible APIs.
#Ready-made analyzers
| Analyzer | For | Chain |
|---|---|---|
arabic | Arabic | unicode_word, nfkc_cf, arabic_normalize, Arabic stop words, arabic_stem |
hebrew, hebrew_query | Hebrew | unicode_word, nfkc_cf, fold, hebrew_lemmatizer |
snowball_<language> | 30 languages, see Snowball stemming | unicode_word, nfkc_cf, the language's stop words, snowball |
cjk | Chinese, Japanese, Korean | unicode_word, cjk_width, lowercase, cjk_bigram, CJK stop words |
code | Source code, identifiers, paths, logs | code tokenizer, code_split, lowercase |
phone | Phone numbers, matched in any format and by trailing digits | phone tokenizer, region US |
phone_search | Phone numbers, matched as whole numbers only | phone_search tokenizer, region US |
cmdline | Command lines, paths, URLs, registry keys | cmdline tokenizer, lowercase |
cmdline_exact | Command lines, case preserved | cmdline tokenizer |
trigram | Substring search over whole values | trigram tokenizer |
The arabic, snowball_<language> and cjk chains follow the Elasticsearch analyzers of the same languages, and hebrew follows the HebMorph analyzer of the Elasticsearch Hebrew plugin, so an index migrated from Elasticsearch matches the same words.
#Through the compatible APIs
Elasticsearch and OpenSearch mappings and Solr schemas are translated to the analyzers in this section. When a translation is not exact, the response carries a warning (a Warning header, and for Solr also a warnings list in the body) that names what differs.
#Elasticsearch and OpenSearch
A text field's analyzer can be a built-in analyzer or one defined in settings.analysis:
curl -X PUT https://api.warpsearch.io/compat/es/articles \
-H "Authorization: Bearer $WARPSEARCH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"settings": {"analysis": {
"analyzer": {
"folded_de": {"type": "custom", "tokenizer": "standard", "filter": ["lowercase", "german_snow"]}
},
"filter": {"german_snow": {"type": "snowball", "language": "German"}}
}},
"mappings": {"properties": {
"title_ar": {"type": "text", "analyzer": "arabic"},
"title_de": {"type": "text", "analyzer": "folded_de"},
"phone": {"type": "text", "analyzer": "phone"}
}}
}'
| Elasticsearch or OpenSearch | WarpSearch |
|---|---|
Analyzers arabic, cjk | The arabic and cjk analyzers |
Analyzers hebrew, hebrew_query (the Elasticsearch Hebrew plugin) | The hebrew and hebrew_query analyzers. hebrew_exact and hebrew_query_light map to them with a warning |
Analyzer english | The same chain as Elasticsearch's: possessives, lowercase, English stop words, Porter stemming |
Analyzers armenian, basque, brazilian, catalan, danish, dutch, estonian, finnish, french, german, greek, hindi, hungarian, indonesian, irish, italian, lithuanian, norwegian, portuguese, romanian, russian, serbian, spanish, swedish, turkish | The snowball_<language> analyzer of that language, with a warning: the stemmer and stop list can differ from Elasticsearch's |
Analyzer thai, tokenizer thai | ICU word segmentation (icu_tokenizer), with a warning: no Thai stop words |
Analyzers and tokenizers phone, phone-search (OpenSearch) | phone and phone_search; phone-region sets default_region |
Tokenizer icu_tokenizer | icu_tokenizer |
Filters snowball, stemmer | snowball. Snowball languages are exact; Elasticsearch's light and minimal stemmers (light_german, light_french, ...) use the Snowball stemmer of the language, with a warning. stemmer arabic is arabic_stem |
Filters arabic_normalization, cjk_width, cjk_bigram, icu_folding, icu_normalizer, icu_transform | The same filters, with their parameters |
Filter reverse | reverse, for a reversed variant |
Filter stop | stop with your word list or _english_. Other predefined lists such as _german_ are dropped with a warning; list the words instead |
Char filters html_strip, mapping, icu_normalizer | The same char filters. mapping needs inline mappings, not mappings_path |
The WarpSearch names code, phone_search, cmdline, cmdline_exact, trigram and snowball_<language> also work as analyzer names in a mapping. Bengali, Bulgarian, Czech, Galician, Latvian, Persian and Sorani have no stemmer here and get the standard analysis, with a warning.
#Solr
Use a language type from Solr's default configset in add-field: text_en, text_ar, text_cjk, text_th, or text_ca, text_da, text_de, text_el, text_es, text_eu, text_fi, text_fr, text_ga, text_hi, text_hu, text_hy, text_id, text_it, text_nl, text_no, text_pt, text_ro, text_ru, text_sv and text_tr, which use the snowball_<language> analyzer of their language.
Or define your own type with add-field-type and use it in the same request or a later one. Name each component by class or by name, as in a Solr schema:
curl -X POST https://api.warpsearch.io/compat/solr/articles/schema \
-H "Authorization: Bearer $WARPSEARCH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"add-field-type": {
"name": "text_fr_folded",
"class": "solr.TextField",
"analyzer": {
"tokenizer": {"class": "solr.ICUTokenizerFactory"},
"filters": [
{"class": "solr.ICUFoldingFilterFactory"},
{"class": "solr.SnowballPorterFilterFactory", "language": "French"}
]
}
},
"add-field": {"name": "title_fr", "type": "text_fr_folded"}
}'
The factories that carry over are the Solr counterparts of the Elasticsearch components above: the ICU tokenizer, folding, normalizer and transform, SnowballPorter, the language stem filters, Arabic normalization and stemming, CJK width and bigrams, Stop, HTMLStrip, LowerCase, ASCIIFolding, KStem, PorterStem and EnglishPossessive. An analyzer can also be a Lucene analyzer class, such as org.apache.lucene.analysis.ar.ArabicAnalyzer. WarpSearch cannot read files from a Solr config set, so a stop or mapping filter that names a file is dropped with a warning. The one exception is lang/stopwords_en.txt, which is the English list. A type with separate indexAnalyzer and queryAnalyzer uses the index analyzer for both, with a warning.
ReverseStringFilterFactory maps to the reverse filter. ReversedWildcardFilterFactory is dropped with a warning: Solr keeps the reversed terms in the same field and rewrites leading wildcards onto them. In WarpSearch, add a reversed variant and query it with rwildcard; see Suffix search.
#Choosing an analyzer
| Your text | Use |
|---|---|
| English | The _t suffix, or snowball_english for more aggressive stemming |
| Another European language, Hindi, Indonesian, Turkish, ... | snowball_<language> |
| Arabic | arabic |
| Hebrew | hebrew |
| Chinese, Japanese, Korean | cjk |
| Several languages in one field | unicode_word with icu_folding, without stemming, or one field per language |
| Names in several scripts | icu_transform to Latin, then icu_folding |
| Code, identifiers, log lines | code |
| Phone numbers | phone |
| Process command lines, file paths, registry keys | cmdline |
Values matched by their ending (*.exe) | A reverse variant and rwildcard, see Suffix search |
| Exact substrings or patterns anywhere in long values | A trigram variant and substring, see Substring search |