Nested Aggregations : grouper par attribut d'un parent


(Thomas Choquet) #1

Bonjour, je cale pour récupérer les résultats d'une agrégation avec des objets imbriqués.

Soit le mapping suivant :

{  
   "mappings":{  
      "client":{  
         "_all":{  
            "enabled":false
         },
         "properties":{  
            "id":{  
               "type":"integer"
            },
            "commande":{  
               "type" : "nested",
               "include_in_parent": true,
               "properties":{  
                  "magasin":{  
                     "type":"string"
                  },
                  "paiement":{  
                     "type":"string"
                  },
                  "montant":{  
                     "type":"integer"
                  },
                  "panier":{  
                     "type" : "nested",
                     "include_in_parent": true,
                     "properties":{  
                        "categorie":{  
                           "type":"string"
                        },
                        "montant":{  
                           "type":"integer"
                        },
                        "quantite":{  
                           "type":"integer"
                        }
                    ...
}

Je veux récupérer la somme des montants des paniers par type de paiement,
( somme des client.commande.panier.montant regroupés par client.commande.paiement)

Si je lance la requête suivante ( :

{
   "size": 0,
   "aggs": {
      "paniers": {
         "aggs": {
            "commande_panier_montant": {
               "sum": {
                  "field": "commande.panier.montant"
               }
            }
         },
         "terms": {
            "field": "commande.paiement",
            "size": "5",
            "order": {
               "commande_panier_montant": "desc"
            }
         }
      }
   }
}

J'obtiens le résultat suivant :

"aggregations": {
      "paniers": {
         "doc_count_error_upper_bound": 0,
         "sum_other_doc_count": 0,
         "buckets": [
            {
               "key": "Carte bancaire",
               "doc_count": 3,
               "commande_panier_montant": {
                  "value": 6537
               }
            },
            {
               "key": "Chèque",
               "doc_count": 2,
               "commande_panier_montant": {
                  "value": 6233
               }
            },
            {
               "key": "Espèce",
               "doc_count": 2,
               "commande_panier_montant": {
                  "value": 6233
               }
            }
         ]
      }
   }

Elasticsearch additionne le montant des paniers de tous les clients contenant au moins une commande avec le moyen de paiement concerné. Ce résultat est donc faux car ce n'est pas l'addition des montants des paniers mais de tous les paniers contenus dans une ligne .

SI je fais une requête en ajoutant une agrégation imbriqué en ajoutant le paramètre suivant :

"nested": {
        "path": "commande"
},

cela donne la requête suivante :

{
   "size": 0,
   "aggs": {
      "paniers": {
         "nested": {
            "path": "commande.panier"
         },
         "aggs": {
            "groupby": {
               "terms": {
                  "field": "commande.paiement",
                  "size": "5",
                  "order": {
                     "commande_panier_montant": "desc"
                  }
               },
               "aggs": {
                  "commande_panier_montant": {
                     "sum": {
                        "field": "commande.panier.montant"
                     }
                  }
               }
            }
         }
      }
   }
}

et cela me renvoi les résultats suivants :

"aggregations": {
      "paniers": {
         "doc_count": 65,
         "groupby": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": []
         }
      }
   } 

Aucun résultat, mais on voit que les 65 paniers ont bien été trouvés car ils apparaissent dans le "doc_count"

Je suppose que le problème vient du fait que "commande.paiement" se situe au dessus de "commande.panier" dans le mapping, et que cela rend l'agrégation impossible à cause du filtrage par "nested": { "path": "commande.panier" }

Est-il possible de faire une requête qui me retournerait l'agrégation imbriqué que je souhaite ?

Merci,
TC


(Camilo Sierra) #2

hello @t.choquet alors sans les data difficile a jouer avec les requetes pour trouve le probleme, apres je dirais que la requete devrait etre du genre :

{
    "size": 0,
    "aggs": {
        "paniers": {
            "nested": {
                "path": "commande"
            },
            "aggs": {
                "groupby": {
                    "terms": {
                        "field": "commande.paiement",
                        "size": "5",
                        "order": {
                            "commande_panier_montant": "desc"
                        }
                    },
                    "aggs": {
                        "montant": {
                            "nested": {
                                "path": "commande.panier"
                            },
                            "aggs": {
                                "commande_panier_montant": {
                                    "sum": {
                                        "field": "commande.panier.montant"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
} 

si ça marche pas, tu peut rajouter aussi un set de data qu'on puisse inserer rapidement pour pouvoir tester ?


(system) #3