Trie agrégation avec termes accentués

Bonjour,

je rencontre un problème de trie dans les résultats d'agrégations renvoyées par élasticsearch. Les infos...

** mapping **
commune_etab: {
     type: 'string',
     analyzer: 'analyzer_keyword'
}
** avec **
analyzer: {
    analyzer_keyword: {
         tokenizer: 'keyword',
         filter: ['lowercase']
}
** Aggregation **
"aggs": {
    "commune_etab": {
        "terms": {
            "field": "commune_etab",
            "size": 0,
            "order": {
                "_term": "asc"
            }
         }
     }
 }
** résultats **
... {
     "name": "curel",
     "path": "curel",
     "count": 1,
     "state": "displayed"
 },
{
     "name": "céreste",
     "path": "céreste",
     "count": 42,
     "state": "displayed"
},
{
     "name": "dauphin",
     "path": "dauphin",
     "count": 4,
     "state": "displayed"
 }, ...

le trie alphabétique ne fonctionne pas avec les accents, ils sont considérés après le "z"...
Sachant que "order" ne prend comme attribut que "_term" et "_count", il ne semble pas possible de modifier l'ordre du tri en introduisant un sous champ avec les même valeurs mais sans les accents.
Existe-t-il un moyen de configurer globalement l'index afin qu'il ne tiennent pas compte des accents pour le trie dans les agrégations ?

Merci pour votre aide !

Il faut mettre un analyseur genre asciifolding token filter pour ça et faire l'aggrégation dessus.

A noter qu'en version 5 c'est un peu plus compliqué car les analyseurs ne sont pas autorisés encore sur les champs de type keyword.

Il faudra donc faire un champ text et activer fielddata dessus.

Quelle est ta version ?

J'utilise la version 2.3.4 et j'ai déjà essayé ça :

analyzer_standard_no_accents: {
tokenizer: 'keyword',
filter: ['lowercase', 'asciifolding']
}

mais les facets obtenues sont sans accents donc le trie est ok mais pas le label...

Je ne suis pas sûr de comprendre ce que tu veux dire...

Il faudra donc faire un champ text et activer fielddata dessus.

Merci pour ton retour

Si tu fournis un script simple complet, je peux t'aider d'avantage.

Regarde par exemple ce script:

Désolé pour le retour tardif mais j'ai dû passer sur un projet plus important :).
Voilà une base de travail :

PUT test
{
  "settings": {
    "analysis": {
      "analyzer": {
        "analyzer_keyword": {
          "tokenizer": "keyword",
          "filter": ["lowercase"]
        },
        "analyzer_standard_no_accents": {
          "tokenizer": "keyword",
          "filter": ["lowercase", "asciifolding"]
        }
      }
    }
  }, 
  "mappings": {
    "lieu": {
      "properties": {
        "titre": {
          "type": "string",
          "analyzer": "standard",
          "fields": {
            "not_analyzed": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "commune": {
          "type": "string",
          "analyzer": "analyzer_keyword",
          "fields": {
            "not_accent": {
              "type": "string",
              "analyzer": "analyzer_standard_no_accents"
            }
          }
        }
      }
    }
  }
}

POST /test/lieu/_bulk?pretty
{"index":{"_id":"1"}}
{ "titre": "Les Magnans", "commune": "Manosque" }
{"index":{"_id":"2"}}
{ "titre": "Gîte Bellevue", "commune": "Melve"}
{"index":{"_id":"3"}}
{ "titre": "Le Pigeonnier", "commune": "Monfort"}
{"index":{"_id":"4"}}
{ "titre": "Hôtel de la Place", "commune": "Mézel"}
{"index":{"_id":"5"}}
{ "titre": "Restaurant le 106", "commune": "la foux d’allos"}

GET /test/lieu/_search
{
  "aggs": {
    "communes": {
      "terms": {
        "field": "commune",
        "size": 0,
        "order": {
          "_term": "asc"
        }
      }
    },
    "communes_sans_accent": {
      "terms": {
        "field": "commune.not_accent",
        "size": 0,
        "order": {
          "_term": "asc"
        }
      }
    }
  }  
}

voilà le résultat de l'aggrégation:

"aggregations": {
    "communes_sans_accent": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "la foux d'allos",
          "doc_count": 1
        },
        {
          "key": "manosque",
          "doc_count": 1
        },
        {
          "key": "melve",
          "doc_count": 1
        },
        {
          "key": "mezel",
          "doc_count": 1
        },
        {
          "key": "monfort",
          "doc_count": 1
        }
      ]
    },
    "communes": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "la foux d’allos",
          "doc_count": 1
        },
        {
          "key": "manosque",
          "doc_count": 1
        },
        {
          "key": "melve",
          "doc_count": 1
        },
        {
          "key": "monfort",
          "doc_count": 1
        },
        {
          "key": "mézel",
          "doc_count": 1
        }
      ]
    }
  }

En gros, je voudrais l'ordre de "communes_sans_accent" mais avec l'affichage accentué de "communes"...

j'espère que ça clarifie mon problème.

Merci pour le script.

Voici comment je ferais (à noter que j'ai adapté à la version 5.2.1 - notamment size: 0 n'est plus supporté):

DELETE test
PUT test
{
  "settings": {
    "analysis": {
      "normalizer": {
        "normalizer_keyword": {
          "filter": ["lowercase"]
        },
        "normalizer_no_accent": {
          "filter": ["lowercase", "asciifolding"]
        }
      }
    }
  }, 
  "mappings": {
    "lieu": {
      "properties": {
        "commune": {
          "type": "keyword",
          "normalizer": "normalizer_keyword",
          "fields": {
            "no_accent": {
              "type": "keyword",
              "normalizer": "normalizer_no_accent"
            }
          }
        }
      }
    }
  }
}

POST /test/lieu/_bulk?pretty
{"index":{"_id":"1"}}
{ "commune": "Manosque" }
{"index":{"_id":"2"}}
{ "commune": "Melve"}
{"index":{"_id":"3"}}
{ "commune": "Monfort"}
{"index":{"_id":"4"}}
{ "commune": "Mézel"}
{"index":{"_id":"5"}}
{ "commune": "la foux d’allos"}

GET /test/lieu/_search
{
  "size": 0,
  "aggs": {
    "communes": {
      "terms": {
        "field": "commune.no_accent",
        "size": 100,
        "order": {
          "_term": "asc"
        }
      },
      "aggs": {
        "communes_sans_accent": {
          "terms": {
            "field": "commune",
            "size": 1
          }
        }
      }
    }
  }
}

Ca te donne:

{
  "took": 6,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 5,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "communes": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "la foux d'allos",
          "doc_count": 1,
          "communes_sans_accent": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
              {
                "key": "la foux d’allos",
                "doc_count": 1
              }
            ]
          }
        },
        {
          "key": "manosque",
          "doc_count": 1,
          "communes_sans_accent": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
              {
                "key": "manosque",
                "doc_count": 1
              }
            ]
          }
        },
        {
          "key": "melve",
          "doc_count": 1,
          "communes_sans_accent": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
              {
                "key": "melve",
                "doc_count": 1
              }
            ]
          }
        },
        {
          "key": "mezel",
          "doc_count": 1,
          "communes_sans_accent": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
              {
                "key": "mézel",
                "doc_count": 1
              }
            ]
          }
        },
        {
          "key": "monfort",
          "doc_count": 1,
          "communes_sans_accent": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
              {
                "key": "monfort",
                "doc_count": 1
              }
            ]
          }
        }
      ]
    }
  }
}

Donc au niveau affichage, tu prends la sous agrégation qui contient l'accent. Le tri étant fait sur la partie sans accent.

Super ! Je l'ai repris pour la version 2.4 et ça marche nickel.

Merci à toi !

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.