Home Articles

Elasticsearch:有没有办法将对象字段的所有(可能是动态的)子字段声明为字符串?

Asked
Viewed 122 times
2

我有一个doc_type,其映射类似于这个非常简化的映射:

{
   "test":{
      "properties":{
         "name":{
            "type":"string"
         },
         "long_searchable_text":{
            "type":"string"
         },
         "clearances":{
            "type":"object"
         }
      }
   }
}

字段 clearances 应该是一个对象,带有一系列字母数字标识符,用于过滤目的 . 典型的文档将具有以下格式:

{
    "name": "Lord Macbeth",
    "long_searchable_text": "Life's but a walking shadow, a poor player, that..."
    "clearances": {
        "glamis": "aa2862jsgd",
        "cawdor": "3463463551"
    }
}

问题在于,有时在索引期间,对象字段 clearances 内的新字段的第一个索引内容将完全是数字的,如上面的情况 . 这会导致Elasticsearch将此字段的类型推断为 long . 但这是一个意外 . 该字段可能是另一个文档中的字母数字 . 当该字段中包含字母数字值的后一个文档到达时,我得到一个解析异常:

{"error":"MapperParsingException[failed to parse [clearances.cawdor]]; nested: NumberFormatException[For input string: \"af654hgss1\"]; ","status":400}%

我尝试用这样定义的动态模板来解决这个问题:

{
   "test":{
      "properties":{
         "name":{
            "type":"string"
         },
         "long_searchable_text":{
            "type":"string"
         },
         "clearances":{
            "type":"object"
         }
      }
   },
   "dynamic_templates":[
      {
         "source_template":{
            "match":"clearances.*",
            "mapping":{
               "type":"string",
               "index":"not_analyzed"
            }
         }
      }
   ]
}

但是,如果第一个索引文档具有可以解析为整数的 clearance.some_subfield 值,它将继续发生,它将被推断为整数,并且在该子字段上具有字母数字值的所有后续文档将无法编入索引 .

我可以列出映射中的所有当前子字段,但它们很多,我希望它们的数量在未来会增长(触发映射的更新以及完全重新索引的需要......) .

每次添加新的子字段时,有没有办法在不使用这种完全重新索引的情况下完成这项工作?

1 Answer

  • 8

    你快到了 .

    首先,动态映射的路径必须在 clearances.* 上,并且它必须是 path_match 而不是普通 match .

    这是一个可运行的例子:https://www.found.no/play/gist/df030f005da71827ca96

    export ELASTICSEARCH_ENDPOINT="http://localhost:9200"
    
    # Create indexes
    
    curl -XPUT "$ELASTICSEARCH_ENDPOINT/play" -d '{
        "settings": {},
        "mappings": {
            "test": {
                "dynamic_templates": [
                    {
                        "clearances_as_string": {
                            "path_match": "clearances.*",
                            "mapping": {
                                "type": "string",
                                "index": "not_analyzed"
                            }
                        }
                    }
                ]
            }
        }
    }'
    
    
    # Index documents
    curl -XPOST "$ELASTICSEARCH_ENDPOINT/_bulk?refresh=true" -d '
    {"index":{"_index":"play","_type":"test"}}
    {"clearances":{"glamis":1234,"cawdor":5678}}
    {"index":{"_index":"play","_type":"test"}}
    {"clearances":{"glamis":"aa2862jsgd","cawdor":"some string"}}
    '
    
    # Do searches
    
    curl -XPOST "$ELASTICSEARCH_ENDPOINT/_search?pretty" -d '
    {
        "facets": {
            "cawdor": {
                "terms": {
                    "field": "clearances.cawdor"
                }
            }
        }
    }
    '
    

Related