Elasticsearch 是一個(gè)分布式、免費(fèi)和開放的搜索和分析引擎,適用于所有類型的數(shù)據(jù),例如文本、數(shù)字、地理空間、結(jié)構(gòu)化和非結(jié)構(gòu)化數(shù)據(jù)。 它基于 Apache Lucene 構(gòu)建,Apache Lucene 是一個(gè)全文搜索引擎,可用于各種編程語言。 由于其速度、可擴(kuò)展性以及對(duì)不同類型內(nèi)容進(jìn)行索引的能力,Elasticsearch 已在多種用例中得到應(yīng)用,例如:
- 企業(yè)搜索
- 日志記錄和日志分析
- 應(yīng)用搜索
- 商業(yè)分析
- 地理空間數(shù)據(jù)分析和可視化
它是如何工作的?
Elasticsearch 不是將信息存儲(chǔ)為列式數(shù)據(jù)行,而是存儲(chǔ)已序列化為 JSON 文檔的復(fù)雜數(shù)據(jù)結(jié)構(gòu)。 每個(gè)文檔由一組鍵(文檔中的字段或?qū)傩缘拿Q)及其相應(yīng)的值(字符串、數(shù)字、布爾值、日期、值數(shù)組、地理位置或其他類型的數(shù)據(jù))組成。 它使用一種稱為倒排索引的數(shù)據(jù)結(jié)構(gòu),列出任何文檔中出現(xiàn)的每個(gè)唯一單詞,并標(biāo)識(shí)每個(gè)單詞出現(xiàn)的所有文檔。
字段類型 - 分析或未分析
Elasticsearch 中的字符串文字要么被分析,要么未被分析。 那么分析到底是什么意思呢? 已分析字段是指在索引之前經(jīng)過分析過程的字段。 然后,該分析的結(jié)果存儲(chǔ)在倒排索引中。 分析過程基本上涉及對(duì)文本塊進(jìn)行分詞和規(guī)范化。 這些字段被分詞為術(shù)語,并且術(shù)語被轉(zhuǎn)換為小寫字母。 這是標(biāo)準(zhǔn)分析器的行為,也是默認(rèn)行為。 但是,如果需要,我們可以指定我們自己的分析器,例如,如果你還想索引特殊字符,而標(biāo)準(zhǔn)分析器則不會(huì)這樣做。如果你想對(duì) analyzer 有更多的了解,請(qǐng)閱讀文章 “Elasticsearch: analyzer”。
我們嘗試使用如下的命令來進(jìn)行分詞:
GET _analyze
{
"analyzer": "standard",
"text" : "Beijing is a beautiful city"
}
Elasticsearch 的標(biāo)準(zhǔn)分析器會(huì)將此文本轉(zhuǎn)換為以下內(nèi)容:
{
"tokens": [
{
"token": "beijing",
"start_offset": 0,
"end_offset": 7,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "is",
"start_offset": 8,
"end_offset": 10,
"type": "<ALPHANUM>",
"position": 1
},
{
"token": "a",
"start_offset": 11,
"end_offset": 12,
"type": "<ALPHANUM>",
"position": 2
},
{
"token": "beautiful",
"start_offset": 13,
"end_offset": 22,
"type": "<ALPHANUM>",
"position": 3
},
{
"token": "city",
"start_offset": 23,
"end_offset": 27,
"type": "<ALPHANUM>",
"position": 4
}
]
}
通配符(wildcard)搜索快速介紹
通配符是特殊字符,充當(dāng)文本值中未知字符的占位符,并且可以方便地查找具有相似但不相同數(shù)據(jù)的多個(gè)項(xiàng)目。 通配符搜索基于查詢中提到的字符與包含這些字符模式的文檔中的單詞之間的字符模式匹配。

現(xiàn)在我們已經(jīng)基本了解了 Elasticsearch 的工作原理、分析字段和通配符搜索是什么,讓我們更深入地了解本文的主題 — 字符串字段并對(duì)其運(yùn)行通配符搜索。
字符串字段和通配符搜索
Elasticsearch 中的每個(gè)字段都有一個(gè)字段數(shù)據(jù)類型。 此類型指示字段包含的數(shù)據(jù)類型(例如字符串或布爾值)及其預(yù)期用途。 Elasticsearch 中可用于字符串的兩種字段類型是 — text(默認(rèn))和 keyword。 它們之間的主要區(qū)別在于,文本字段在索引時(shí)進(jìn)行分析,而關(guān)鍵字字段則不然。 這意味著,文本字段在索引之前會(huì)被標(biāo)準(zhǔn)化并分解為單獨(dú)的分詞,而關(guān)鍵字字段則按原樣存儲(chǔ)。 此外,由于文本字段已標(biāo)準(zhǔn)化,因此它們支持不區(qū)分大小寫的搜索。 為了對(duì)關(guān)鍵字字段實(shí)現(xiàn)相同的效果,我們必須在創(chuàng)建索引時(shí)定義一個(gè) normalizer,然后在定義字段映射時(shí)指定相同的 normalizer。有關(guān) nomalizer 的詳細(xì)介紹,請(qǐng)閱讀文章 “Elasticsearch:詞分析中的 Normalizer 的使用”。
PUT wildcard
{
"settings": {
"analysis": {
"normalizer": {
"lowercase_normalizer": {
"type": "custom",
"char_filter": [],
"filter": [
"lowercase",
"asciifolding"
]
}
}
}
},
"mappings": {
"properties": {
"text-field": {
"type": "text"
},
"keyword-field": {
"type": "keyword",
"normalizer": "lowercase_normalizer"
}
}
}
}
現(xiàn)在進(jìn)行通配符查詢,假設(shè)我們有以下文檔,并且我們想要對(duì)其運(yùn)行一些通配符搜索:
PUT wildcard/_doc/1
{
"text-field": "Mockingbirds don’t do one thing but make music for us to enjoy.",
"keyword-field": "Mockingbirds don’t do one thing but make music for us to enjoy."
}
如下所示的查詢可以很好地處理文本字段:
GET wildcard/_search?filter_path=**.hits
{
"_source": false,
"fields": [
"text-field"
],
"query": {
"wildcard": {
"text-field": {
"value": "*birds*"
}
}
}
}
上面的搜索返回結(jié)果:
{
"hits": {
"hits": [
{
"_index": "wildcard",
"_id": "1",
"_score": 1,
"fields": {
"text-field": [
"Mockingbirds don’t do one thing but make music for us to enjoy."
]
}
}
]
}
}
然而,下面的搜索則不會(huì):
GET wildcard/_search?filter_path=**.hits
{
"_source": false,
"fields": [
"text-field"
],
"query": {
"wildcard": {
"text-field": {
"value": "*birds*music*"
}
}
}
}
它返回的結(jié)果是:
{
"hits": {
"hits": []
}
}
原因是,該字段的單詞已被分析并存儲(chǔ)為分詞。 因此,elasticsearch 無法找到與給定表達(dá)式(*birds*music*)對(duì)應(yīng)的分詞。
但是,這適用于關(guān)鍵字字段,因?yàn)樗鼈儼丛瓨哟鎯?chǔ)。我們來嘗試如下的搜索:
GET wildcard/_search?filter_path=**.hits
{
"_source": false,
"fields": [
"keyword-field"
],
"query": {
"wildcard": {
"keyword-field": {
"value": "*birds*music*"
}
}
}
}
上面的命令返回的結(jié)果是:
{
"hits": {
"hits": [
{
"_index": "wildcard",
"_id": "1",
"_score": 1,
"fields": {
"keyword-field": [
"mockingbirds don't do one thing but make music for us to enjoy."
]
}
}
]
}
}
現(xiàn)在,讓我們討論從 ElasticSearch v7.9 引入的另一個(gè)字符串字段——通配符。 這是一種專門的字段類型,主要用于非結(jié)構(gòu)化機(jī)器生成的內(nèi)容。更多閱讀,請(qǐng)參閱文章 “Elasticsearch:使用新的 wildcard 字段更快地在字符串中查找字符串 - 7.9 新功能”。
以下是對(duì)這 3 種字段類型運(yùn)行幾個(gè)通配符查詢的性能統(tǒng)計(jì)數(shù)據(jù):



我們可以清楚地看到,關(guān)鍵字字段的性能在所有搜索查詢和索引大小中是最一致的。 文本字段也做得不錯(cuò),但它們不能用于搜索像 *Elastic*stash* 這樣的值,這使得關(guān)鍵字類型成為明顯的贏家。
那么為什么要引入通配符字段呢? 那么,引入通配符字段是為了解決文本和關(guān)鍵字字段存在的以下限制:
- 文本字段 - 將任何通配符表達(dá)式的匹配限制為單個(gè)分詞,而不是字段中保存的原始整個(gè)值。
- 關(guān)鍵字字段 - 當(dāng)搜索子字符串和有許多唯一值時(shí),關(guān)鍵字字段的速度很慢。 關(guān)鍵字字段還存在數(shù)據(jù)大小限制的缺點(diǎn)。 默認(rèn)字符串映射會(huì)忽略長度超過 256 個(gè)字符的字符串。 這可以擴(kuò)展到單個(gè)令牌 32k 的 Lucene 硬限制。 當(dāng)您嘗試搜索系統(tǒng)日志和類似文檔時(shí),這可能會(huì)產(chǎn)生問題。
通配符字段解決了上述限制。 它不會(huì)將字符串視為由標(biāo)點(diǎn)符號(hào)分隔的標(biāo)記集合,而是通過首先對(duì)所有文檔進(jìn)行近似匹配,然后對(duì)通過匹配接收到的文檔子集應(yīng)用詳細(xì)比較來執(zhí)行模式匹配。
文本、關(guān)鍵字和通配符字段之間的詳細(xì)比較可以在此處閱讀。
上述統(tǒng)計(jì)信息是通過在 v8.9 上運(yùn)行的 elasticsearch 索引上運(yùn)行搜索獲得的,映射如下:
{
"wildcard-search-demo-index": {
"mappings": {
"properties": {
"field1": {
"type": "text"
},
"field2": {
"type": "keyword"
},
"field3": {
"type": "wildcard"
}
}
}
}
}
索引的文檔在所有字段中具有統(tǒng)一的數(shù)據(jù),即文檔中的所有 3 個(gè)字段都具有相同的值。 例如,
"hits": [
{
"_index": "wildcard-search-demo-index",
"_type": "_doc",
"_id": "vlPiHYYB6ikeelRg4I8n",
"_score": 1.0,
"_source": {
"field1": "It started as a scalable version of the Lucene open-source search framework then added the ability to horizontally scale Lucene indices.",
"field2": "It started as a scalable version of the Lucene open-source search framework then added the ability to horizontally scale Lucene indices.",
"field3": "It started as a scalable version of the Lucene open-source search framework then added the ability to horizontally scale Lucene indices."
}
},
{
"_index": "wildcard-search-demo-index",
"_type": "_doc",
"_id": "v1PiHYYB6ikeelRg4I87",
"_score": 1.0,
"_source": {
"field1": "Elasticsearch allows you to store, search, and analyze huge volumes of data quickly and in near real-time and give back answers in milliseconds.",
"field2": "Elasticsearch allows you to store, search, and analyze huge volumes of data quickly and in near real-time and give back answers in milliseconds.",
"field3": "Elasticsearch allows you to store, search, and analyze huge volumes of data quickly and in near real-time and give back answers in milliseconds."
}
}
]
綜上所述,字段類型的選擇并沒有固定的規(guī)則。 它取決于多種因素,例如數(shù)據(jù)類型、必須涵蓋的不同用例集等。
在設(shè)置數(shù)據(jù)存儲(chǔ)時(shí),決定字段類型是一個(gè)非常關(guān)鍵的因素,因?yàn)樗鼧O大地影響性能,并且應(yīng)該通過考慮所有可能的場(chǎng)景和因素來決定。
Elasticsearch 還有一種稱為通配符的查詢類型,可用于運(yùn)行通配符查詢。?
另外值得指出的是:由于通配符搜索帶來很多的性能問題,有時(shí)甚至?xí)缘艉芏嗟南到y(tǒng)資源。在生成環(huán)境中,有的建議關(guān)掉這個(gè)功能以避免影響系統(tǒng)的運(yùn)行。建議閱讀文章:
-
Kibana:如何在 Kibana 中禁止查詢中使用前置通配符(wildcard)查詢文章來源:http://www.zghlxwxcb.cn/news/detail-705349.html
-
Elasticsearch:如何提高查詢性能文章來源地址http://www.zghlxwxcb.cn/news/detail-705349.html
到了這里,關(guān)于Elasticsearch:wildcard - 通配符搜索的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!