【问题标题】:Find documents in Elasticsearch where `ignore_malformed` was triggered在 Elasticsearch 中查找触发了 `ignore_malformed` 的文档
【发布时间】:2017-08-28 14:00:40
【问题描述】:

默认情况下,如果将数据插入不适合现有类型的字段,Elasticsearch 会引发异常。例如,如果已将字段创建为数字类型,则插入包含该字段的字符串值的文档会导致错误。

可以通过启用 ignore_malformed 设置来更改此行为,这意味着这些字段将被静默忽略以用于索引目的,但保留在 _source 文档中 - 这意味着无法搜索或聚合无效值,但仍然存在包含在返回的文档中。

这在我们的用例中是更可取的行为,但我们希望能够以某种方式找到此类文档,以便将来修复它们。

有没有办法以某种方式标记某些格式错误的字段被忽略的文档?我们完全控制文档插入过程,因此我们可以修改所有插入标志,或进行试插入或任何操作,以达到我们的目标。

【问题讨论】:

    标签: elasticsearch malformed


    【解决方案1】:

    您可以使用exists 查询来查找该字段不存在的文档,请参阅此示例

    PUT foo
    {
      "mappings": {
        "bar": {
          "properties": {
            "baz": {
              "type": "integer",
              "ignore_malformed": true
            }
          }
        }
      }
    }
    
    PUT foo/bar/1
    {
      "baz": "field"
    }
    
    GET foo/bar/_search
    {
      "query": {
        "bool": {
          "filter": {
            "bool": {
              "must_not": [
                {
                  "exists": {
                    "field": "baz"
                  }
                }
              ]
            }
          }
        }
      }
    }
    

    虽然没有专门的机制,所以这个搜索也会找到没有故意设置字段的文档

    【讨论】:

    • 我很难区分具有该字段(但格式错误)的文档和没有该字段的文档。我需要某种搜索来检查该字段是否作为索引存在,但确实存在于“_source”中。除此之外,问题是我有 1000 个不同的字段,找到任何有冲突的字段都会很棘手。
    【解决方案2】:

    你不能,当你在 elasticsearch 上搜索时,你不是在文档源上搜索,而是在包含分析数据的倒排索引上搜索。

    ignore_malformed 标志表示“始终存储文档,如果可能进行分析”。

    你可以尝试,创建一个格式错误的文档,然后使用_termvectors API 看看文档是如何分析并存储在倒排索引中的,如果是字符串字段,你可以看到一个“数组”是存储为空字符串等。但该字段将存在。

    所以忘记倒排索引,让我们使用源代码!

    1. 滚动所有数据,直到找到异常,我使用一个小的 Python 脚本来搜索滚动、反序列化并测试每个文档的字段类型(很长),但我可以错误文档 ID 列表。

    2. 使用脚本查询可能会很长并且会导致集群崩溃,请谨慎使用,可能是post_filter

    这里我要检索country_name不是字符串的文档:

    {
       "_source": false,
       "timeout" : "30s",
        "query" : {
            "query_string" : {
                "query" : "locale:de_ch"
            }
        },
        "post_filter": {
            "script": {
                "script": "!(_source.country_name instanceof String)"
            }
        }
    }
    
    • "_source:false" => 我只想要文档 ID
    • “超时” => 防止崩溃

    如您所见,这是一个缺失的功能,我知道 logstash 会标记 失败的文档,所以 elasticsearch 可以实现同样的事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-13
      • 2015-01-14
      • 2017-11-19
      • 2016-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多