Elasticsearch: Trier par sous-agrégation scripted_metric

Créé le 14 nov. 2014  ·  94Commentaires  ·  Source: elastic/elasticsearch

Puisqu'il existe une nouvelle agrégation de métrique scriptée (scripted_metric) dans la version 1.4, il est possible de faire beaucoup de choses incroyables.
Par exemple, il est possible d'implémenter l'agrégation moyenne pondérée, ce qui nous manquait auparavant.

Maintenant, il nous manque vraiment une possibilité de trier par résultats scripted_metric .

Exemple en direct :

Nous calculons weightedAvgVis avec scripted_metric et voulons obtenir des identifiants avec les 5 valeurs TOP de weightedAvgVis . Puisque le script renvoie le double, cela semble logiquement possible.

{  
   "from":0,
   "size":0,
   "query":{  
      "match_all":{   }
   },
   "aggregations":{  
      "idNodes":{  
         "terms":{  
            "field":"id",
            "size":5,
            "order":{  
               "weightedAvgVis":"asc"
            }
         },
         "aggregations":{  
            "weightedAvgVis":{  
               "scripted_metric":{  
                  "init_script":"_agg['weightedSum'] = 0d; _agg['countSum'] = 0L;",
                  "map_script":"_agg['weightedSum'] = _agg.weightedSum + _source['avgVis'] * _source['count']; _agg['countSum'] = _agg.countSum + _source['count'];",
                  "reduce_script":"weightedSum = 0d; countSum = 0L; for(a in _aggs) {weightedSum += a.weightedSum; countSum += a.countSum;};if(countSum == 0L) {return 0d;} else {return weightedSum / countSum}"
               }
            }
         }
      }
   }
}
:AnalyticAggregations >enhancement feedback_needed help wanted high hanging fruit

Commentaire le plus utile

@ colings86 , @clintongormley

Vous nous avez demandé (le 19 août) de décrire les cas d'utilisation de cette fonctionnalité. De nombreuses personnes de la communauté ont publié leurs cas d'utilisation. Après plus de 3 mois, je pense raisonnable d'obtenir une réponse officielle d'ElasticSearch.

Comme mentionné dans ce fil, cette fonctionnalité est prise en charge par Crate.io (basé sur ElasticSearch) et par Solr mais n'est toujours pas prise en charge par ES. Je pense que nous aimons tous ES mais il devient très difficile (du moins pour moi) de comprendre / accepter cette fonctionnalité manquante.

Veuillez nous donner une réponse ou mieux encore une solution!

Tous les 94 commentaires

@eryabitskiy c'est quelque chose auquel j'ai réfléchi mais qui nécessite que quelques problèmes en suspens soient d'abord résolus. Plus précisément, il s'agit de https://github.com/elasticsearch/elasticsearch/pull/8421 et https://github.com/elasticsearch/elasticsearch/issues/8434. Celles-ci nous permettraient de spécifier des chemins de commande beaucoup plus puissants et la méthode getProperty sur l'agrégation métrique scriptée pourrait être utilisée pour récupérer des propriétés arbitraires des résultats des scripts.

Salut, je ne sais pas si cela est approprié, mais j'ai pensé que vous voudriez peut-être évaluer l'intérêt. Nous sommes très impatients de voir cela également. Actuellement, nous finissons par effectuer beaucoup de tri sur des ensembles de résultats surdimensionnés dans Go, alors que pouvoir trier sur des métriques scriptées nous éviterait ces tracas.

+1 Ce serait génial si résolu!

+1

+1

: +1: trier sur des agrégations de métriques scriptées serait une fonctionnalité qui tue. En attendant, nous effectuons également un tri côté client sur les résultats surdimensionnés.

+1

+1

+1

+1

+1 Outre les autres cas d'utilisation mentionnés ici, cette fonctionnalité conférerait au produit Kibana une force majeure, en particulier pour le prototypage rapide.

+1

+1

(sautant sur le train en marche "+1 pour cette fonctionnalité")

+1

+1

+1

+1

+1

+1

+1

+1

+1

Concernant le calcul de la moyenne pondérée, j'ai envoyé une pull request pour étendre l'agrégation moyenne actuelle afin de prendre en charge ce type de moyenne de manière native sans métrique scriptée.

Voici le problème créé sur github:
https://github.com/elastic/elasticsearch/issues/15731

Voici la pull request (seule la première approche est implémentée):
https://github.com/elastic/elasticsearch/pull/15781

En ce qui concerne la prise en charge de la clause de commande pour la métrique scriptée, j'ai envoyé une requête d'extraction pour la prendre en charge.

https://github.com/elastic/elasticsearch/pull/15718

+1

+1

+1

+1

+1

+1

+1

+1

Dans l'attente de celui-ci ...

+1

@ elasticsearch-guys, Y a-t-il une chance d'intégrer rapidement ma pull request ou une amélioration de celle-ci.

+1

+1

+1

+1

J'ai vraiment besoin de cette fonctionnalité, veuillez l'ajouter :)
+1

+1 Ce serait une excellente fonctionnalité

+1

+1

+1

Existe-t-il actuellement une autre approche que le tri côté client? Essayer de trier à la volée sur une moyenne pondérée spécifiée par l'utilisateur.

+1, (et un joli s'il vous plaît) 😄

+1

+1

+1

+1

Je voudrais comprendre les cas d'utilisation où les utilisateurs souhaitent passer une commande par une agrégation scripted_metric . Les utilisateurs qui commandent actuellement par une agrégation scripted_metric peuvent-ils répondre avec une brève description de ce que fait l'agrégation de métrique scriptée et quelle est la description générale de la demande de recherche? (si vous pouvez également inclure le corps de la requête et les scripts, probablement dans un lien essentiel sur votre commentaire plutôt que dans le texte pour qu'il soit facile à lire)

Mon cas d'utilisation: j'ai des petites annonces dans les villes. Lorsqu'un utilisateur se trouve dans une ville spécifique, je souhaite afficher le nombre total de petites annonces dans les villes voisines (<50 km), et trier ces villes voisines par distance.

Donc, fondamentalement, je fais une agrégation de termes pour regrouper les petites annonces par ville (afin que je puisse obtenir le nombre total de petites annonces par ville), puis je fais une agrégation scripted_metric pour obtenir la distance de la ville d'origine pour chaque groupe de villes que je reçois, car Je n'ai pas trouvé d'autre moyen d'y parvenir. Je dois enfin trier l'agrégation initiale avec la distance que j'ai obtenue.

Ma requête: https://gist.github.com/raphaelMalie/203e411fddb64d75444014d3f28e6f8e

@ colings86 Voici un exemple simplifié de ce que j'essaie de faire: http://stackoverflow.com/questions/37799130/elasticsearch-sort-terms-by-pipeline-bucket-script-aggregation

Comme autre exemple à clarifier, disons que j'ai 10 000 noms d'étudiants et que je souhaite créer un tableau montrant les 10 meilleurs étudiants en fonction des notes et les notes sont déterminées en combinant les valeurs de plusieurs champs. Je veux donc pouvoir faire un agrégat de termes sur le nom et le classer par note (un agrégat bucket_script qui calcule plusieurs champs). Sans les commander, je devrais renvoyer les 10000 étudiants avec leurs notes et faire un tri côté client pour ne voir que les 10 meilleurs.

Merci. 👍

@raphaelMalie J'ai commenté votre essence avec une suggestion sur la façon dont vous pourriez être en mesure d'éviter l'agg scripted_metric dans votre cas (commenté ici pour que nous puissions avoir une conversation là-bas si nécessaire plutôt que de se perdre sur ce fil) .

Merci à @clintongormley de m'avoir aidé avec la solution

@ chevin99 dans votre exemple de notes que représentent les différents documents de l'index? (par exemple, un étudiant et ses notes à tous les tests)

@ colings86 chaque document représenterait un score de test et d'autres informations sur le test qui seraient utilisées pour calculer la note / note globale.

est-ce que cela aide? https://gist.github.com/chevin99/930c537be7caf2e22abdcf1086350c55

@ colings86 Voici le type de requêtes que nous avons implémentées avec des métriques scriptées.

Pour toutes ces requêtes, nous utilisons la clause "ORDER BY" pour calculer un top 10 par exemple.

IMO, un meilleur moyen de résoudre ces différentes requêtes pourrait être de prendre en charge la moyenne pondérée de manière native et d'étendre la fonction avg pour prendre en charge une autre variante de la moyenne comme le deuxième exemple. De plus, pour notre cas, nous n'avons pas vraiment besoin d'un top 10 totalement précis, nous avons juste besoin d'une bonne approximation (probablement un cas d'utilisation courant).

@ colings86 C'est mon cas d'utilisation, impossible de trouver un moyen de faire quelque chose comme ça dans ES 2.3.5 actuellement.

SELECT TOP 3 Name, SUM(Value) [Value] FROM <strong i="7">@table</strong>
GROUP BY Name 
ORDER BY ABS(SUM(Value)) DESC

Prenez les N premiers résultats classés par agrégation avec la fonction appliquée (ABS dans ce cas). L'agrégation est donc effectuée en premier (à l'aide de scripted_metric map reduction), puis elle doit être triée en fonction du résultat pour obtenir les 3 premiers.

Plus d'infos ici
SQL Style GroupBy & OrderBy avec fonction dans ES?

@ colings86 Donc, la motivation de mon problème est toujours d'

1) Nous avons un calendrier des activités pour chaque sujet .
2) La chronologie est stockée dans des documents par jour pour chaque sujet séparément.
3) Pour obtenir une activité pendant une certaine période sur plusieurs sujets, nous utilisons l'agrégation des termes par topicID et des agrégations sous-scriptées pour chaque champ d'activité.
4) Le problème que dans ce cas, vous obtenez une activité pour tous les sujets et c'est trop. Nous avons besoin d'une pagination pour réduire le nombre de sujets calculés en même temps. Et pour cela, nous avons besoin d'un tri (le tri sur topicID n'aide pas, car nous avons d'abord besoin des sujets les plus actifs).

Je veux dire qu'il existe une propriété de taille pour l'agrégation des termes, mais son utilisation est très limitée, alors que vous ne pouvez trier que par termes.

PS En outre, le décalage serait bien pour la pagination ... mais le tri est un très bon début.
PS2 Maintenant, nous chargeons les tuples topicID + sortingFiledValue sur WebServer, faisons le tri + paginer et charger les sujets de page. Toute fonctionnalité permettant de déplacer le tri / la pagination vers ES serait utile.

Salut @ colings86!

Vous pouvez regarder https://discuss.elastic.co/t/ordering-terms-aggregation/47791 pour voir mon cas d'utilisation par exemple:

Supposons que nous ayons des documents avec des champs (group_id, price, x,...) . Notre objectif est de:

  1. exécuter une requête qui filtre l'ensemble des documents;
  2. regrouper les documents par group_id ;
  3. dans chaque groupe, récupérez le document avec la x élevée, appelons-le un "représentant du groupe";
  4. prenez le price et commandez tous les groupes par ce price (commandez les groupes en fonction du prix de leurs représentants).

J'ai également essayé d'utiliser scripted_metric pour implémenter cette requête. J'ai réussi avec le calcul de la métrique scriptée souhaitée representative_price pour chaque bucket, mais quand il s'agissait de commander terms par elle, j'ai trouvé que c'était impossible.

Salut @ colings86

Y a-t-il des progrès / plan pour ce problème?

ElasticSearch 5.0 est là, mais toujours pas de prise en charge du "tri par" sur la métrique scriptée.

+1

+1

+1

+1

+1024!

Salut @ colings86 , voici un cas d'utilisation très simple.

Mon index ES est composé de documents qui stockent:

  • Une date (une journée complète)
  • Un référent
  • Le nombre d'affichages d'une annonce sur ce référent
  • Le nombre de clics sur cette annonce sur ce référent

Je souhaite afficher les 10 meilleurs référents ayant le meilleur taux de conversion entre les impressions et les clics. Je peux avoir plus de 10000 référents.
Voici l'exemple de requête:
https://gist.github.com/bpolaszek/00fec1dedc0ed02263f2328a9c0cd161

Cela vient avec # 4915.
Bien sûr, je pourrais stocker le taux de conversion sur chaque document, mais le CTR n'est qu'une des nombreuses mesures dont j'ai besoin et j'ai une énorme quantité de données. Et les scripts en ligne sont destinés à cela :)

En outre, le regroupement, le tri et le découpage sont disponibles dans le monde SQL, bien que le choix d'un moteur NoSQL pour l'analyse de rendu soit évident en 2016.

Aujourd'hui, je dois charger silencieusement une quantité arbitraire d'agrégations (999999 pour être _ presque_ sûr d'avoir tous mes référents, trier moi-même le résultat et découper le résultat d'agrégation de 10 à 20 si l'utilisateur final passe à la page 2, par exemple) . C'est vraiment ennuyeux.

Ces 2 fonctionnalités sont vraiment obligatoires si nous voulons qu'ES soit un véritable moteur de BI - ces fonctionnalités existent dans Apache SolR depuis quelques années, par exemple. Mais j'adore ES et je préfère attendre que ces fonctionnalités soient implémentées :)

Merci beaucoup pour votre considération,
Ben

@ colings86 , @clintongormley

Vous nous avez demandé (le 19 août) de décrire les cas d'utilisation de cette fonctionnalité. De nombreuses personnes de la communauté ont publié leurs cas d'utilisation. Après plus de 3 mois, je pense raisonnable d'obtenir une réponse officielle d'ElasticSearch.

Comme mentionné dans ce fil, cette fonctionnalité est prise en charge par Crate.io (basé sur ElasticSearch) et par Solr mais n'est toujours pas prise en charge par ES. Je pense que nous aimons tous ES mais il devient très difficile (du moins pour moi) de comprendre / accepter cette fonctionnalité manquante.

Veuillez nous donner une réponse ou mieux encore une solution!

Le tri de l'agrégation des termes par n'importe quelle sous-agrégation (à l'exception de min et max) a une erreur sans limite pour la même raison que le tri par nombre croissant a une erreur illimitée qui est décrite dans https://github.com/elastic/elasticsearch/ issues / 17614 # issueecomment -244114209. Ce problème est également abordé dans https://github.com/elastic/elasticsearch/issues/17588. Pour être clair, le problème ici n'est pas que nous calculons une valeur avec une erreur par rapport à la valeur vraie, comme nous le faisons avec d'autres agrégations telles que l'agrégation de cardinalité et même avec les termes d'agrégation lorsqu'ils sont triés par nombre décroissant de documents. La différence entre le tri des termes agrégation par une sous-agrégation et d'autres agrégations qui, étant donné une approximation de la valeur vraie, est que dans le cas du tri par sous-agrégation, l'erreur est illimitée (c'est-à-dire que nous n'avons aucune connaissance de l'ampleur de l'erreur. ) alors qu'avec les autres agrégations mentionnées, nous pouvons soit calculer l'erreur du cas le plus défavorable, soit avoir une bonne idée de l'erreur attendue. Cela signifie que les résultats renvoyés lors de la commande des termes par une sous-agrégation ne sont même pas une bonne approximation des vraies valeurs.

Actuellement, le paramètre de tri pour l'agrégation des termes peut être _count , _term une agrégation qui produit un seul nombre. L'agrégation scripted_metric peut renvoyer n'importe quel objet (y compris des structures complexes) et n'est pas limitée à renvoyer une valeur numérique. Changer le tri pour prendre en charge d'autres agrégations en dehors des contraintes ci-dessus n'est pas trivial et rendrait le code de tri beaucoup plus complexe (par exemple, un défi serait que nous aurions besoin d'un moyen de nous assurer que les valeurs renvoyées par les agrégations sont triables. ).

L'agrégation scripted_metric était destinée à être utilisée principalement pour le prototypage et nous n'envisagions pas qu'elle soit utilisée de cette manière. Parce que cela ajouterait plus de cas où l'erreur dans l'agrégation des termes est illimitée et comme l'ajout de la prise en charge de cela ne serait pas trivial, nous ne pensons pas qu'il soit correct d'ajouter cette fonctionnalité. Ce que nous aimerions faire à la place, c'est travailler pour ajouter la prise en charge des cas d'utilisation mentionnés d'autres manières, comme l'ajout de nouvelles agrégations qui les prennent en charge.

D'après les commentaires ci-dessus, il semble y avoir trois principaux cas d'utilisation:

  1. Regroupement sur un terme et tri des groupes par un calcul impliquant le résultat d'une agrégation multiple sur le contenu du groupe. C'est un problème délicat à résoudre pour les mêmes raisons que celles énumérées ci-dessus.
  2. Agrégation moyenne pondérée - Cela pourrait être implémenté en tant que nouveau type d'agrégation et il y a un problème à discuter ici: https://github.com/elastic/elasticsearch/issues/15731
  3. L'équivalent de SQL Group by - il existe quelques formes différentes de ceci répertoriées ici:

    • Groupe SQL par trié par valeur de champ - nous avons une proposition pour implémenter cette fonctionnalité ici: https://github.com/elastic/elasticsearch/issues/21833

    • Grouper SQL par avec une agrégation avec des groupes triés par cette agrégation - c'est en fait très similaire à 1.

@ colings86

Je veux juste clarifier les choses.

Le tri de l'agrégation des termes par n'importe quelle sous-agrégation (à l'exception de min et max) a une erreur sans limite pour la même raison que le tri par nombre croissant a une erreur illimitée qui est décrite dans ....

En même temps, il y a un exemple de la documentation qui montre le tri également par agrégation AVG non seulement min et max.
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html#search -aggregations-bucket-terms-aggregation-order
"order" : { "avg_play_count" : "desc" }

QUESTION: Ai-je bien compris que cet exemple de la documentation avec avg est un dysfonctionnement et pourrait renvoyer des résultats erronés?

Sinon, je ne vois aucun avantage de l'agrégation avg sur l'agrégation scriptée renvoyant une valeur flottante / double primitive (dans le cas de min et max, je vois certainement la différence).

QUESTION: Ai-je bien compris que cet exemple de la documentation avec avg est un dysfonctionnement et pourrait renvoyer des résultats erronés?

Oui, c'est vrai et c'est un bogue dans la documentation que je corrigerai pour être plus clair. Notez également qu'il y a une note en haut de cette section qui avertit que le tri par sous-agrégation est déconseillé.

Sinon, je ne vois aucun avantage de l'agrégation moyenne par rapport à l'agrégation scriptée renvoyant une valeur flottante / double primitive

Il n'y a aucun avantage et le tri des termes agrégation par une agrégation moyenne présente les mêmes écueils à cet égard.

J'ai ouvert https://github.com/elastic/elasticsearch/pull/22032 pour résoudre le problème de documentation

@ colings86

Merci pour votre réponse!

Je comprends qu'il y a toujours un échange entre performance et précision, en particulier dans le moteur FTS. Mais si vous récupérez tous les buckets de shard, vous pouvez toujours atteindre une précision de 100%.

Et je soupçonne qu'en fait la plupart des gens accepteraient que tous les seaux soient renvoyés de chaque fragment dans un souci de précision à 100% sur les performances et la consommation de mémoire (nous pouvons voter pour le vérifier). Nous le faisons déjà côté serveur Java de toute façon.

En outre, vous pouvez toujours définir une propriété de taille maximale du protecteur qui déclenche une erreur en cas de consommation de mémoire excessive lors de telles requêtes.

Pouvez-vous envisager une telle fonctionnalité?

+1.

Pour mon cas d'utilisation, j'ai en fait besoin de récupérer tous les buckets, puis de les trier et de les découper côté client.
Cela ne détruit pas seulement les performances, cela détruit également l'expérience du développeur.

Et je soupçonne qu'en fait la plupart des gens accepteraient que tous les seaux soient renvoyés de chaque fragment dans un souci de précision à 100% sur les performances et la consommation de mémoire (nous pouvons voter pour le vérifier).

Nous ajoutons uniquement des fonctionnalités à Elasticsearch qui sont évolutives horizontalement. Tout ce que nous ajoutons devrait fonctionner lorsque vous exécutez un nœud sur votre ordinateur portable avec 50 Go de données ou 1000 nœuds dans votre serveur de données avec 50 Po de données.

La récupération de tous les termes de tous les fragments ne se met pas à l'échelle horizontalement et nous ne l'ajouterons donc pas.

Nous le faisons déjà côté serveur Java de toute façon.

Exactement. C'est un problème qui devrait être résolu côté client à la place (où vous connaissez les limites de vos données et combien vous devrez évoluer).

Je vois...

Ensuite, je peux mentionner un cas d'utilisation évolutif horizontalement: si chaque compartiment est entièrement alloué avec une partition (en utilisant également le champ de termes comme routage), vous pouvez simplement récupérer uniquement les principaux compartiments des fragments et obtenir des résultats précis. Malheureusement, cela ne fonctionne qu'avec un routage approprié.

@ colings86

Afin de pouvoir utiliser une agrégation pour trier l'agrégation de termes, elle doit être _actuellement_ une agrégation de métrique numérique. Les agrégations de pipeline sont une autre famille d'agrégations que les agrégations de métriques et ne peuvent pas être utilisées pour le tri. Vous ne pouvez pas trier à l'aide d'une agrégation de pipeline car ils ne sont exécutés que dans la phase de réduction sur le nœud de coordination et vous ne disposez donc pas des informations sur le fragment afin de pouvoir trier les compartiments de fragments pour choisir les N premiers à envoyer au nœud de coordination.

Existe-t-il un plan qui remplira cette fonctionnalité?
Existe-t-il un plan qui supprimera la restriction concernant l'agrégation numérique-métrique?
Existe-t-il un plan qui prendra en charge la métrique d'agrégation de pipeline sur le nœud ou la partition?

À mon avis, ces agrégations, pertinentes pour le calcul comme la somme / min / max / moyenne / nombre, etc., sont toutes des métriques, le résultat n'est pas au format numérique. Par exemple:
{ "first_student":{ "min": { "field": "first_name" } } }
Cela aidera beaucoup qu'elasticsearch suporte largement différents types de métriques. Ainsi, il sera plus puissant que les outils traditionnels d'analyse de données SQL.

Je déplace actuellement mes analyses vers une plate-forme SQL à cause de cela.
Cas d'utilisation simple et fréquent: calculer les progressions entre les métriques agrégées (ie CTR: + 15%) et trier par progression. Impossible de faire avec ES sans stocker la progression au préalable.

@ colings86

Actuellement, je vais essayer de traduire différents types de mesures de script de bucket dans les formes de script de réduction de carte dans une méthode générale, puis la phase de commande de ces mesures peut être prise en charge.
Je pense qu'il faut des calculs de grande taille ou répétés, ce qui entraînera des performances destructrices et une efficacité relativement faible.
Une autre solution est que les côtés client exécutent la phase de commande. Cette solution nécessite les énormes résultats (sinon le résultat de la commande sera de mauvaise précision) dérivés de l'agrégation d'elaticsearch.
Compte tenu du transfert de big data et du manque de support de calcul distribué côté client, cette solution sera plus inefficace.

Une autre solution est que les côtés client exécutent la phase de commande. Cette solution nécessite les énormes résultats (sinon le résultat de la commande sera de mauvaise précision) dérivés de l'agrégation d'elaticsearch.

Cela nécessite la connaissance de la quantité de valeurs renvoyées par l'agrégation. Vous ne pouvez pas demander à ES de "renvoyer tous les compartiments" sur une agrégation et vous devez spécifier un nombre limite arbitraire, ce qui est complètement absurde et nuit aux performances.

@anhzhi J'ai du mal à trouver le texte que vous avez cité pour le contexte (désolé si je l'ai manqué dans les commentaires ci-dessus), pourriez-vous coller le lien vers le commentaire ou la documentation dans laquelle vous l'avez vu? La déclaration est cependant très vraie.

Existe-t-il un plan qui remplira cette fonctionnalité?

Si vous parlez de la possibilité de trier l'agrégation des termes par une agrégation de pipeline, je ne vois pas comment cela serait possible à mettre en œuvre. L'agrégation de termes doit trier les compartiments collectés sur la partition afin de ne renvoyer que le nombre shard_size d'entre eux au nœud de coordination. S'il n'effectuait pas ce tri sur le fragment, il devrait renvoyer tous les compartiments qu'il a collectés au nœud de coordination qui ne serait pas mis à l'échelle car le nombre de compartiments peut être très important pour les champs à cardinalité élevée.

Donc, étant donné que nous devons trier sur le fragment, la seule autre solution serait de «pousser» le calcul des agrégations de pipeline sur les fragments. Mais cela ne fonctionnerait pas non plus, car les agrégations de pipeline en leur cœur comparent les résultats finaux de différentes agrégations (pensez à la dérivée où vous comparez les valeurs finales dans des buckets consécutifs ou en divisant deux agrégations de somme). Sur le fragment, le résultat final n'est pas connu car ce résultat dépend des résultats de tous les fragments et non pas d'un seul, donc si vous calculiez la valeur uniquement en fonction des informations sur ce fragment, le résultat serait presque certainement faux et pire il pourrait être très affectée par les résultats des autres fragments, ce ne serait même pas une bonne estimation de la valeur finale.

Donc, pousser le calcul de l'agrégation de pipeline sur les fragments n'aide pas non plus à trier l'agrégation de termes par agrégations de pipeline.

Si vous faisiez plutôt référence au tri des termes d'agrégation par les agrégations scripted_metric, cela a été discuté dans https://github.com/elastic/elasticsearch/issues/8486#issuecomment -265457470 et nous avons décidé que plutôt que nous préférerions ne pas ajouter plus cas où l'erreur dans l'agrégation des termes est illimitée, nous aimerions donc plutôt essayer de résoudre les cas d'utilisation spécifiques de l'agrégation scripted_metric.

Existe-t-il un plan qui supprimera la restriction concernant l'agrégation numérique-métrique?

Il n'y a pas de plans pour le moment. Nous avons besoin d'une valeur pour comparer les buckets afin de les trier et une valeur numérique nous donne une valeur qui peut toujours être comparée sans compliquer l'API. D'autre part, les objets arbitraires ne se comparent pas naturellement, l'API devrait donc être rendue plus complexe et plus difficile à utiliser pour prendre en charge cela.

Existe-t-il un plan qui prendra en charge la métrique d'agrégation de pipeline sur le nœud ou la partition?

Voir mes commentaires sur votre première question ci-dessus

À mon avis, ces agrégations, pertinentes pour le calcul comme la somme / min / max / moyenne / nombre, etc., sont toutes des métriques, le résultat n'est pas au format numérique. Par exemple:
{"first_student": {"min": {"field": "first_name"}}}

Je ne suis pas sûr de comprendre cela car la sortie de l'agrégation min est une valeur double singulière. Pour le reste de l'API, nous enveloppons cela dans un objet afin que vous puissiez y accéder dans la réponse, mais à des fins de comparaison lors du tri, il s'agit d'une valeur double singulière, et surtout nous savons que ce sera toujours une valeur double singulière. nous pouvons le valider dans la requête avant d'exécuter la requête.

Une autre solution est que les côtés client exécutent la phase de commande. Cette solution nécessite les énormes résultats (sinon le résultat de la commande sera de mauvaise précision) dérivés de l'agrégation d'elasticsearch.
Compte tenu du transfert de big data et du manque de support de calcul distribué côté client, cette solution sera plus inefficace.

Malheureusement, cela est également vrai pour Elasticsearch lui-même en raison des raisons que j'ai exposées en réponse à votre première question; que nous avons besoin des informations de tous les fragments pour pouvoir calculer les résultats des agrégations de pipeline afin de pouvoir effectuer le tri.

J'adorerais trouver une solution à cela mais je ne vois pas comment nous pourrions le faire à ce stade de manière fiable et évolutive dans les contraintes du sharding.

@ colings86 Le texte cité provient de
https://github.com/elastic/elasticsearch/issues/14101 ou
https://discuss.elastic.co/t/ordering-terms-aggregation-based-on-pipeline-metric/31839/7
Je fais référence aux deux aspects que vous avez mentionnés:

  • trier l'agrégation des termes par une agrégation de pipeline , telle que bucket_script
  • trier l'agrégation des termes par les agrégations scripted_metric
    exemple comme suit:
{
   "query": {
      "bool": {
         "filter": [
            {
               "query_string": {
                  "query": "*",
                  "analyze_wildcard": true
               }
            }
         ],
         "must": [
            {
               "range": {
                  "@timestamp": {
                     "to": 1505804143152,
                     "from": 1505800543152
                  }
               }
            }
         ]
      }
   },
   "from": 0,
   "aggs": {
      "http.client_ip.topn": {
         "terms": {
            "field": "http.client_ip",
            "order":[{
               # only normal metric aggregation supported
               # while script metric aggregation or bucket-script pipeline aggregation not supported
                "sum_bytes_total": "desc"
            }],
            "size": 10
         },
         "aggs": {
            "sum_bytes_total": {
               "sum": {
                  "script": "doc['http.bytes_in'].value+doc['http.bytes_out'].value"
               }
            },
            "bucket_script_metric": {
               "bucket_script": {
                  "buckets_path": {
                     "sum_bytes_total": "sum_bytes_total"
                  },
                  "script": {
                     "lang": "groovy",
                     "inline": "sum_bytes_total"
                  }
               }
            },
            "mr_script_metric": {
               "scripted_metric": {
                  "init_script": "params._agg.bytes_total = []",
                  "map_script": "params._agg.bytes_total.add(doc['http.bytes_in'].value+doc['http.bytes_out'].value)",
                  "combine_script": "double bytes_total = 0; for (item in params._agg.bytes_total) { bytes_total += item } return bytes_total",
                  "reduce_script": "double bytes_total = 0; for (a in params._aggs) { bytes_total += a } return bytes_total"
               }
            }
         }
      }
   },
   "size": 0
}

Maintenant, je comprends ce que vous dites. Je pense qu'il a besoin de quelques améliorations supplémentaires pour les algorithmes de calcul distribué et les cadres logiciels d'ElasticSearch.
J'attends toujours avec impatience votre nouvelle version, de nouvelles innovations et de nouvelles solutions sur l'analyse du Big Data.

@anhzhi , totalement d'accord. Le calcul distribué est un gros échec pour toute analyse de Big Data. En ce moment précis, j'ai besoin de faire une telle chose, mais je suis juste déçu quand j'ai atteint et lu ce fil.

@tberne @anzhi J'ai quitté ElasticSearch pour cette raison: je devais trier les métriques scriptées et créer des facettes de plage. Comme ES n'était pas en mesure de fournir cela, j'avais l'habitude de récupérer tous les documents et de faire cette logique du côté PHP, ce qui était complètement contre-productif et nuisible aux performances.

La semaine dernière j'ai livré une nouvelle version de cette application sur laquelle j'ai travaillé pendant plusieurs mois, et le moteur de stockage est désormais basé sur MariaDb Columnstore (le seul moteur SQL open-source qui stocke les données dans des colonnes au lieu de lignes). Les performances ne sont pas aussi bonnes qu'ElasticSearch (et INSERT / UPDATE / DELETE prend des années), mais au moins, la création de métriques scriptées et leur tri (SELECT SUM (bytes_in + bytes_out) AS sum_bytes_total [...] ORDER BY sum_bytes_total DESC) est un morceau de gâteau et les performances sont acceptables (requêtes d'environ ~ 150 ms sur des tables avec des dizaines de millions de lignes). Bien sûr, vous n'avez pas de facettes (agrégations) prêtes à l'emploi et vous devez les créer vous-même, ce qui est plus compliqué à faire que ES, mais au moins cela fonctionne, et toute la logique se fait dans le moteur de stockage. ; plus de choses délicates pour terminer un comportement non pris en charge.

Auparavant, je pensais qu'ElasticSearch était le bon choix en tant que moteur principal d'une application de BI, mais je me suis trompé: ElasticSearch est parfait pour le texte intégral, pas pour l'analyse.

Auparavant, je pensais qu'ElasticSearch était le bon choix en tant que moteur principal d'une application de BI, mais je me suis trompé: ElasticSearch est parfait pour le texte intégral, pas pour l'analyse.

Je ne pourrais pas être plus d'accord. ES est tout simplement parfait lorsqu'il s'agit de recherche en texte intégral. Même avec un scénario d'agrégation simple, c'est un outil de mise à mort. Mais lorsque nous commençons à faire une analyse sérieuse, il manque des choses importantes.

Je ne sais pas encore, mais je pense que je vais garder ES comme un stockage de données volumineuses et, peut-être, je présenterai l'utilisation d'un processeur de flux (comme Apache Flink) pour consolider certaines données vers ES.

@bpolaszek - Vous ne pouvez pas obtenir le taux de conversion par référent et par annonce en utilisant la disposition de script dans l'agrégation de la somme et la somme en utilisant la même chose. Cela peut être utilisé plus tard pour commander les référents.
Quelque chose comme ci-dessous est ce que j'ai à l'esprit -

{
   "aggs" : {
             "refereres" : {
                         "terms" : { "field" : "referer" },
                         "order" : "sumOfConvertion" 
                      },
                 "aggs" : {
                        "convertionSum" : {
                                    "sum" : { "script" : " doc['clicks'].value / doc['views'].value "}
                            }
                 }
}

Il existe une solution avec ES qui nécessite toujours un tri côté client, mais qui devrait être plus efficace pour récupérer tous les résultats dont vous avez besoin afin de les trier: essayez l' agrégat composite qui vous permet de récupérer tous les résultats (avec pagination) et ensuite vous pouvez faire un tri par fusion côté client.

Discussion très intéressante! Je me demande comment Solr a résolu cela efficacement?

Existe-t-il une nouvelle fonctionnalité qui permettrait cela, sans récupérer tous les résultats et trier côté client? Notre cas d'utilisation est similaire: calculer le CTR (clics / impressions) sur les champs agrégés et trier les résultats par les valeurs les plus élevées.

Discussion très intéressante! Je me demande comment Solr a résolu cela efficacement?

Existe-t-il une nouvelle fonctionnalité qui permettrait cela, sans récupérer tous les résultats et trier côté client? Notre cas d'utilisation est similaire: calculer le CTR (clics / impressions) sur les champs agrégés et trier les résultats par les valeurs les plus élevées.

AFAIK Solr n'a pas non plus résolu ce problème.

Merci @bpolaszek

Il semble que dans notre cas, nous pouvons fragmenter / acheminer les données, ce qui signifie que les données de chaque requête de recherche vivront toujours sur le même serveur et qu'il ne serait pas nécessaire de les mélanger autour du cluster.

Nous envisageons d'écrire un plugin personnalisé pour nous permettre de trier sur les champs calculés. Des suggestions sur la façon dont cela pourrait être réalisé, compte tenu de la limitation de routage ci-dessus? J'ai jeté un œil aux plugins existants mais je n'ai rien trouvé de similaire.

+1

Numéro +1. Aide à ajouter du support

Existe-t-il des solutions de contournement pour le moment?

Parce qu'il y a encore une activité sur ce bogue, j'aime mentionner une solution:

Nous avons ajouté une transformation dans 7.2 que vous pouvez utiliser pour regrouper les données, les agréger et les réécrire dans l'index secondaire. Il offre beaucoup de liberté, par exemple scripted metric . Au moins la demande initiale du démarreur de fil peut être résolue en utilisant une transformation. Dans la première étape, vous pouvez regrouper les données et appliquer l'agrégation personnalisée (métrique scriptée). Ensuite, la destination peut être interrogée pour obtenir les n premiers résultats.

Cette solution est évolutive et fonctionne avec une grande quantité de données. À partir de 7.3 la transformation peut s'exécuter en mode continu et mettre à jour la destination.

Cela paraît bien! Avez-vous un exemple de requête? (Je ne suis plus en ES, mais toujours curieux 😀)

Cette page vous a été utile?
0 / 5 - 0 notes