web-dev-qa-db-fra.com

Migrer le type de champ du texte vers le mot-clé sur Elasticsearch

Quand je veux changer le type d'un champ de texte en mot-clé avec cette commande:

PUT indexStat/_mapping/StatCateg
{
  "StatCateg":{
    "properties": {
      "nom_categorie": {
        "type":"keyword","index": true
      }
    }
  }
}

J'ai ce message:

{
  "error": {
    "root_cause": [
      {
        "type": "illegal_argument_exception",
        "reason": "mapper [nom_categorie] of different type, current_type [text], merged_type [keyword]"
      }
    ],
    "type": "illegal_argument_exception",
    "reason": "mapper [nom_categorie] of different type, current_type [text], merged_type [keyword]"
  },
  "status": 400
}
10
C.Rouillon

OK enfin je vois dans la doc qu'il n'est pas possible de changer le type de données d'un champ:

Mise à jour des mappages existants

En dehors des cas documentés, les mappages de types et de champs existants ne peuvent pas être mis à jour. Changer le mappage signifierait invalider les documents déjà indexés. Au lieu de cela, vous devez créer un nouvel index avec les mappages corrects et réindexer vos données dans cet index.

La seule solution est donc de:

  • Recréez un nouvel index avec de bons types de données
  • Réindexer les données avec API de réindexation
14
C.Rouillon

La modification des types de données (mappages) d'un index existant n'est pas non prise en charge . pour ce faire, créez un nouvel index avec les bons types (mappages) et reindex vos données.

Élastique blogpost à propos de cette opération et vous recommande d'utiliser une approche de meilleures pratiques d'alias de votre index.


Si tu ne le fais pas ???? avoir un index alias

Ce sont les étapes nécessaires, la prochaine fois sera plus facile sans temps d'arrêt

  1. Obtenir le mappage actuel de StatCateg
  2. Créez un nouvel index StatCateg_v1 avec les mappages corrects
  3. Réindexer de StatCateg à StatCateg_v1
  4. Supprimez l'ancien index StatCateg
  5. Créez un alias StatCateg_v1 -> StatCateg (de sorte que la prochaine fois ce sera plus facile à faire sans temps d'arrêt)

Exemple d'extrait (en python):

import requests

current_index_name = 'StatCateg'
new_index_name = 'StatCateg-v1'
base_url = 'https://...'
mapping_changes = {
    "nom_categorie": {"type": "keyword"}
}

# ------------------------------------------------
# Get current mapping
r = requests.get('{base_url}/{index_name}'.format(base_url=base_url, index_name=current_index_name))
r.raise_for_status()
content = r.json()
mappings = content[current_index_name]['mappings']
mappings['properties'].update(mapping_changes)

# ------------------------------------------------
# Create a new index with the correct mappings
r = requests.put('{base_url}/{index_name}'.format(base_url=base_url, index_name=new_index_name), json={
    'mappings': mappings
})
r.raise_for_status()

# ------------------------------------------------
# Reindex
r = requests.post('{base_url}/_reindex'.format(base_url=base_url), json={
    "source": {
        "index": current_index_name
    },
    "dest": {
        "index": new_index_name
    }
})
r.raise_for_status()

# ------------------------------------------------
# Delete the old index
r = requests.delete('{base_url}/{index_name}'.format(base_url=base_url, index_name=current_index_name))
r.raise_for_status()

# ------------------------------------------------
# Create an alias (so that on next time this will be easier to do without downtime)
r = requests.post('{base_url}/_aliases'.format(base_url=base_url), json={
    "actions": [
        {"add": {
            "alias": current_index_name,
            "index": new_index_name
        }}
    ]
})
r.raise_for_status()

Dans le cas où vous DO avez un index aliasé

Ce sont les étapes nécessaires, pas de temps d'arrêt

  1. Obtenir le mappage actuel de StatCateg_v1
  2. Créez un nouvel index StatCateg_v2 avec les mappages corrects
  3. Réindexer à partir de StatCateg_v1 à StatCateg_v2
  4. Permuter les alias (StatCateg_v1 -> StatCateg) avec (StatCateg_v2 -> StatCateg)
  5. Supprimez l'ancien index StatCateg_v1

Exemple d'extrait (en python):

import requests

index_name = 'StatCateg'
current_index_name = 'StatCateg_v1'
next_index_name = 'StatCateg_v2'
base_url = 'https://...'
mapping_changes = {
    "nom_categorie": {"type": "keyword"}
}

# ------------------------------------------------
# Get current mapping
r = requests.get('{base_url}/{index_name}'.format(base_url=base_url, index_name=current_index_name))
r.raise_for_status()
content = r.json()
mappings = content[current_index_name]['mappings']
mappings['properties'].update(mapping_changes)

# ------------------------------------------------
# Create a new index with the correct mappings
r = requests.put('{base_url}/{index_name}'.format(base_url=base_url, index_name=next_index_name), json={
    'mappings': mappings
})
r.raise_for_status()

# ------------------------------------------------
# Reindex
r = requests.post('{base_url}/_reindex'.format(base_url=base_url), json={
    "source": {
        "index": current_index_name
    },
    "dest": {
        "index": next_index_name
    }
})
r.raise_for_status()

# ------------------------------------------------
# Replace old index alias with new  
r = requests.post('{base_url}/_aliases'.format(base_url=base_url), json={
    "actions": [
        {"remove": {
            "alias": index_name,
            "index": current_index_name
        }},
        {"add": {
            "alias": index_name,
            "index": next_index_name
        }}
    ]
})
r.raise_for_status()

# ------------------------------------------------
# Delete the old index
r = requests.delete('{base_url}/{index_name}'.format(base_url=base_url, index_name=current_index_name))
r.raise_for_status()
1
Jossef Harush