简体   繁体   中英

How do I aggregate over top_hits results in elasticsearch

Here are example documents:

{
    "player": "Jim",
    "score" : 5
    "timestamp": 1459492890000
}

{
    "player": "Jim",
    "score" : 7
    "timestamp": 1459492895000
}

{
    "player": "Dave",
    "score" : 9
    "timestamp": 1459492894000
}

{
    "player": "Dave",
    "score" : 4
    "timestamp": 1459492898000
}

I want to get the latest score for each player and then get the average of all those scores. So the answer would be 5.5. Jim's latest score is 7 and Dave's latest score is 4. The average between those two is 5.5

The only way I found to get the "latest" document of a player was to use the top_hits aggregation. However, it does not seem that I am able to do another aggregation after I get the latest document.

This is the best I came up with:

{
  "aggs": {
    "last_score": {
      "terms": { "field": "player" },
      "aggs": {
        "last_score_hits": {
          "top_hits": {
            "sort": [ { "timestamp": { "order": "desc" } } ],
            "size": 1
          },
          "aggs": {
            "avg_score": {
              "avg": { "field": "score" }
            }
          }
        }
      }
    }
  }
}

However, this gives me this error:

Aggregator [last_score_hits] of type [top_hits] cannot accept sub-aggregations

If there is another way to accomplish this search without using top_hits as well, then I would be all for it.

You can have other aggregation on a parallel level of top_hit but you cannot have any sub_aggregation below top_hit. It is not supported by ElasticSearch. here is the link to Github issue

You can have a parallel level aggregation like:

"aggs": {
    "top_hits_agg": {
        "top_hits": {
            "size": 10,
            "_source": {
              "includes": ["score"]
            }
        }
    },
    "avg_agg": {
        "avg": {
            "field": "score"
        }
    }
}

You're trying to put avg_score as a sub-aggregation of last_score_hits . To get success you have to put avg_score as a sub-aggregation of last_score . See an example bellow:

{
  "aggs": {
    "last_score": {
      "terms": {
        "field": "player"
      },
      "aggs": {
        "last_score_hits": {
          "top_hits": {
            "sort": [
              {
                "timestamp": {
                  "order": "desc"
                }
              }
            ],
            "size": 1
          }
        },
        "avg_score": {
          "avg": {
            "field": "score"
          }
        }
      }
    }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM