我們知道在文檔攝入到 Elasticsearch 時,如果文檔的字段在 mapping 中已經(jīng)有定義,而當(dāng)前的文檔的字段的類型和之前的類型是不一樣的情況下,那么我們該如何處理呢?通常由如下的幾種方法:
- 使用?coerce?屬性。在這種情況下,即便不同類型的數(shù)據(jù)被寫入到相應(yīng)的字段,在能夠相互轉(zhuǎn)換的情況下,它的寫入也可以是成功的。請詳細(xì)閱讀文章 “Elasticsearch:Elasticsearch 中的數(shù)據(jù)強(qiáng)制匹配” 及 “Elasticsearch:如何將浮點(diǎn)值存儲到整型字段中”。
- 通過 ingest pipeline 或者 Logstash 進(jìn)行數(shù)據(jù)轉(zhuǎn)換再寫入到 Elasticsearch。
上面的方法只適用于在能夠轉(zhuǎn)換的條件下才可以實(shí)現(xiàn),比如 “1” => 1 的轉(zhuǎn)換。但是,在有些情況下,我們的這種轉(zhuǎn)換是根本不可行的,比如 "one" => 1。首先這種數(shù)據(jù)的類型是根本不一樣,而且即便強(qiáng)制轉(zhuǎn)換,也會失敗。
那么出現(xiàn)這種情況,一種是直接丟棄該文檔,這會造成文檔的丟失,即使是一個字段的類型不匹配。那么我們是否有其它的方式呢來處理這個文檔呢?比如丟失這個不符合的字段,而攝入其它的字段。
忽略不符合索引映射的字段,并避免在使用 Elasticsearch 攝取期間丟棄文檔。一個幾乎不為人知的名為 ignore_malformed 的設(shè)置如何在因?yàn)閱蝹€字段格式錯誤而完全刪除文檔或忽略該字段并無論如何攝取文檔之間產(chǎn)生差異。
ignore_malformed
有時你對收到的數(shù)據(jù)沒有太多控制權(quán)。 一個用戶可以發(fā)送一個 login 字段,它是一個 date,另一個用戶可以發(fā)送一個 login 字段,它是一個電子郵件地址。
嘗試將錯誤的數(shù)據(jù)類型索引到字段中會默認(rèn)引發(fā)異常,并拒絕整個文檔。 ignore_malformed 參數(shù),如果設(shè)置為 true,則允許忽略異常。 格式錯誤的字段沒有被索引,但文檔中的其他字段被正常處理。
在本文中,我將解釋設(shè)置 ignore_malformed 如何影響 100% 的丟棄率和 100% 的成功率(即使只是忽略一些格式錯誤的字段)。
映射是如何工作的
我喜歡將 Elasticsearch 視為一個基于文檔的 NoSQL 數(shù)據(jù)庫,其中不需要預(yù)先定義索引的模式。 Elasticsearch 將從第一個文檔或包含新字段的任何后續(xù)文檔推斷 schema。
或者,你可以預(yù)先提供一個 schema(在 Elasticsearch 術(shù)語中稱為映射 mapping),并且你的所有文檔都需要遵循該 schema。
實(shí)際上,情況并非非黑即白。 你還可以為每個文檔提供僅涵蓋部分字段(可能是最常見的)的部分模式,并讓 Elasticsearch 找出更多動態(tài)字段的 schema。
當(dāng)數(shù)據(jù)格式錯誤時會發(fā)生什么?
無論你是預(yù)先指定映射還是 Elasticsearch 自動推斷映射。 如果文檔只顯示一個與索引映射不匹配的字段,Elasticsearch 將刪除整個文檔并在客戶端日志中返回警告。
如果客戶不查看這些日志而錯過了警告,就會出現(xiàn)大問題。 他們可能永遠(yuǎn)不會發(fā)現(xiàn)哪里出了問題,或者更糟的是,如果所有后續(xù)文檔的格式都錯誤,Elasticsearch 甚至可能會完全停止攝取數(shù)據(jù)。
上述情況聽起來非常災(zāi)難性,但完全有可能發(fā)生,尤其是在你無法完全控制數(shù)據(jù)質(zhì)量的情況下。 想想用戶生成的文檔。
Elasticsearch 中可能有一個非常未知的設(shè)置可以準(zhǔn)確解決上述問題。 這個字段從 Elasticsearch 2.0 開始就有了。 我們在這里談?wù)摴爬系臍v史,因?yàn)樵谧珜懕疚臅r最新版本是 8.8。
示例用例
為了更方便地與 Elasticsearch 交互,我將在這里使用 Kibana(Elasticsearch 的前端工具)和 Dev Tools?控制臺。
以下示例摘自 Elasticsearch 官方文檔。
我在這里通過提供一些關(guān)于幕后發(fā)生的事情的更多細(xì)節(jié)來擴(kuò)展這個例子。
首先,我們要定義 2 個字段,它們都是整數(shù)類型,但只有一個字段定義了 ignore_malformed 。
PUT my-index-000001
{
"mappings": {
"properties": {
"number_one": {
"type": "integer",
"ignore_malformed": true
},
"number_two": {
"type": "integer"
}
}
}
}
如果你嘗試使用以下命令獲取生成的映射:
GET my-index-000001/_mapping
你講得到如下的結(jié)果:
{
"my-index-000001": {
"mappings": {
"properties": {
"number_one": {
"type": "integer",
"ignore_malformed": true
},
"number_two": {
"type": "integer"
}
}
}
}
}
然后我們提取兩個示例文檔:
PUT my-index-000001/_doc/1
{
"text": "Some text value",
"number_one": "foo"
}
PUT my-index-000001/_doc/2
{
"text": "Some text value",
"number_two": "foo"
}
文檔 1 被正確攝取,而文檔 2 反而返回以下錯誤消息。
{
"error": {
"root_cause": [
{
"type": "document_parsing_exception",
"reason": "[3:17] failed to parse field [number_two] of type [integer] in document with id '2'. Preview of field's value: 'foo'"
}
],
"type": "document_parsing_exception",
"reason": "[3:17] failed to parse field [number_two] of type [integer] in document with id '2'. Preview of field's value: 'foo'",
"caused_by": {
"type": "number_format_exception",
"reason": "For input string: \"foo\""
}
},
"status": 400
}
如果你隨后使用以下查詢搜索相同的索引:
GET my-index-000001/_search
{
"fields": [
"*"
],
"_source": true
}
你會看到只有第一個文檔(id=1)被正確攝取。
{
"took": 659,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1,
"hits": [
{
"_index": "my-index-000001",
"_id": "1",
"_score": 1,
"_ignored": [
"number_one"
],
"_source": {
"text": "Some text value",
"number_one": "foo"
},
"fields": {
"text.keyword": [
"Some text value"
],
"text": [
"Some text value"
]
},
"ignored_field_values": {
"number_one": [
"foo"
]
}
}
]
}
}
從上面的 JSON 響應(yīng)中,你可以注意到幾件事:
- 現(xiàn)在有一個 _ignored 類型的字段,其中包含在攝取此文檔時被忽略的所有字段的列表。
- 有一個字段 ignored_field_values 帶有忽略字段及其值的字典。
- 字段 source 包含未修改的原始文檔。 如果你想稍后修復(fù)映射問題,這將特別有用。
結(jié)論
你可以從今天開始在你的索引上使用 ignore_malformed ,只需添加到你的索引設(shè)置,創(chuàng)建映射時添加到單個字段,或者添加到索引模板以使具有特定索引模式的所有索引成為默認(rèn)選項。 為了簡潔起見,我不會在這里展示如何將此設(shè)置用于索引、索引模板或組件模板。 請參閱官方文檔或繼續(xù)關(guān)注有關(guān)該主題的更多文章。文章來源:http://www.zghlxwxcb.cn/news/detail-735429.html
Elastic 目前正在努力使此設(shè)置成為 Elasticsearch 8.9 的默認(rèn)設(shè)置。文章來源地址http://www.zghlxwxcb.cn/news/detail-735429.html
到了這里,關(guān)于Elasticsearch:ignore_malformed,映射異常的解藥的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!