首页 > 技术文章 > (57)ElasticSearch重建索引且保证应用程序不用重启

javasl 2020-04-12 17:45 原文

  ElasticSearch中字段的类型一旦确定就不能修改,如果我们要修改其类型就要重新建mapping。然后把旧索引中的数据批量导入到新索引中。同时采用给索引起别名的方式使客户端应用程序不需要重启。

  1、演示字段类型一旦确定不能修改

  添加文档,同时默认创建了索引

PUT index1/type1/1
{
  "content":"2000-11-11"
}

  查询字段类型,content类型为date

GET index1/type1/_mapping
{
  "index1": {
    "mappings": {
      "type1": {
        "properties": {
          "content": {
            "type": "date"
          }
        }
      }
    }
  }
}

  添加字符串类型的文档报错。因为该字段已经映射成date类型了,要实现添加字符串类型的,那么必须把content的类型修改为string

PUT index1/type1/1
{
  "content":"I like Java"
}
{
  "error": {
    "root_cause": [
      {
        "type": "mapper_parsing_exception",
        "reason": "failed to parse [content]"
      }
    ],
    "type": "mapper_parsing_exception",
    "reason": "failed to parse [content]",
    "caused_by": {
      "type": "illegal_argument_exception",
      "reason": "Invalid format: \"I like Java\""
    }
  },
  "status": 400
}

  直接修改不成功,报错

PUT index1/_mapping/type1
{
  "properties": {
    "content":{
      "type":"text"
    }
  }
}
{
  "error": {
    "root_cause": [
      {
        "type": "illegal_argument_exception",
        "reason": "mapper [content] of different type, current_type [date], merged_type [text]"
      }
    ],
    "type": "illegal_argument_exception",
    "reason": "mapper [content] of different type, current_type [date], merged_type [text]"
  },
  "status": 400
}

  2、演示旧索引中的数据导入到新索引中

  在应用程序中,应用程序连接的是别名,我们只需要把别名关联不同的索引即可实现重建索引且保证应用程序不用重启

  1)给index1起别名为index2

PUT /index1/_alias/index2

  2)创建新索引

PUT /newindex
{
  "mappings": {
    "type1":{
      "properties": {
        "content":{
          "type":"text"
        }
      }
    }
  }
}

  3)执行先查询旧索引再导入到新索引操作

  由于旧索引中数据量可能很大,批量查询的时候,建议采用scroll api,并且采用多线程并发的方式来reindex数据,每次scroll就查询指定日期的一段数据,交给一个线程即可。

  示例:批量查询旧索引index1

GET /index1/type1/_search?scroll=1m
{
  "query": {
    "match_all": {}
  },
  "sort": ["_doc"],
  "size":2
}

  示例:批量导入新索引newindex

POST /_bulk
{"index":{"_index":"newindex","_type":"type1","_id":1}}
{"content":"1988-08-08"}

  4)删除index2与index1的别名关联,增加index2与newindex的别名关联

POST _aliases
{
  "actions": [
    {
      "remove": {
        "index": "index1",
        "alias": "index2"
      }
    },
    {
      "add": {
        "index": "newindex",
        "alias": "index2"
      }
  }
  ]
}

  5)查询验证

GET index2/type1/_search

  查询结果,可以看出index2关联的是新的索引(newindex中的数据是"content": "1988-08-08")

{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1,
    "hits": [
      {
        "_index": "newindex",
        "_type": "type1",
        "_id": "1",
        "_score": 1,
        "_source": {
          "content": "1988-08-08"
        }
      }
    ]
  }
}

 

推荐阅读