由Elasticsearch7.8评分脚本引起的一个索引迁移解决方法

175 阅读2分钟

前言

为了实践一下ElasticSearch的自定义相关度评分,使用了Expression脚本。但是在执行过程中却报错了,最后通过修改索引映射,添加别名和同步旧索引数据得以解决,所以以下也围绕这几项问题展开。

涉及知识

索引映射修改

索引别名使用

重建索引

相关度评分

问题

1.评分脚本执行报错。

当前索引是一个普通的产品数据,包括产品ID,产品名称,产品别名,产品品类,价格,排序编号。下面只是想搜索某产品名,按照排序编号的相关度相乘的排序方式,但是却报错。 (注:_search下取文档的值是doc, 其他情况下ctx)

GET products_new/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "goods_name": 12
        }
      },
      "script_score": {
        "script": {
          "lang": "expression",
          "source": "_score * doc['goods_sort']"
        }  
      }
    }
  }
}

2.修改索引映射报错。

根据报错提示是因为脚本中执行的字段非数据,非日期和非地理位置类型,所以就需要对之前索引的字段类型进行修改。但是索引映射对字段的修改只能添加属性不能修改,mapper [goods_sort] of different type, current_type [keyword], merged_type [long],解决这个就需要重建索引。

索引重建

1.给旧索引添加别名。
POST /_aliases
{
  "actions": [
    {
      "add": {
        "index": "products",
        "alias": "products_alias"
      }
    }
  ]
}
2.根据旧索引创建新字段类型的映射。
PUT products_new 
{
  "mappings": {
    "properties": {
      "class_id": {
        "type": "long"
      },
      "goods_name": {
        "type": "text",
        "analyzer": "ik_smart"
      },
      "goods_sort": {
        "type": "long"
      },
      "id": {
        "type": "long"
      },
      "price": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256  
          }
        }
      },
      "single_goods_name": {
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "state": {
        "type": "long"
      }
    }
  }
}
3.同步旧索引数据到新索引。
POST /_reindex
{
  "source": {
    "index": "products"
  },
  "dest": {
    "index": "products_new"
  }
}
4.给新索引添加和旧索引相同的别名并移除旧索引别名。
POST /_aliases
{
  "actions": [
    {
      "add": {
        "index": "products_new",
        "alias": "products_alias"
      },
      "remove": {
        "index": "products",
        "alias": "products_alias"
      }
    }
  ]
}
5.删除旧索引。
DELETE products
{

}
6.通过别名使用脚本评分。
GET products_alias/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "goods_name": 12
        }
      },
      "script_score": {
        "script": {
          "lang": "expression",
          "source": "_score * doc['goods_sort']"
        }  
      }
    }
  }
}

为什么要给旧索引创建了别名,又后面移除再删除。那是因为修改了索引映射相当于进行了业务调整,为了不影响程序添加别名的情况下。等数据全部同步后再移除和删除就不会影响到业务了。