user7112484
user7112484

Reputation:

How to perform a search based on aggregation?

I have an elasticsearch index whose documents are setup similar to that of the following: each document holds a survey participant and their answers to questions involving their favorite video game console and video games. Here is an example document (all of the mappings are keywords):

_source: {
    "console": "Nintendo Switch"
    "games": ["Cuphead", "Star Fox", "Super Mario World", "Resident Evil"],
}

Using terms aggregation, I can see the top results for both video game consoles and video games respectively; however, I want to see what the top favorite video games are among my participants, ordered by the preferred console, all in descending order.

[
    {
        "console": "Nintendo Switch",  # doc_count = 10_000
        "games": [
                "Super Smash Bros. Ultimate",  # doc_count = 4_000
                "Cuphead",  # doc_count = 2_300
                "Deus Ex Mankind Divided",  # doc_count = 900 
                ...
            ]
    }, 
    {
        "console": "Playstation 4",  # doc_count = 9_000
        "games": [
                "Super Smash Bros. Ultimate",  # doc_count = 4_000
                "Crash Bandicoot",  # doc_count = 3_000
                "Cuphead",  # doc_count = 2_300
                ...
            ]
    }, 
    ...
]

My first instinct was to take the results of the term aggregation for top video game consoles, and for each result returned perform a search like so:

GET master/_search
{
  "size": 10,
  "aggs": {
    "a1": {
      "terms": { 
        "field": "games"
      }
    }
  },
  "query": {
    "term": {
      "console": "CONSOLE_NAME_HERE"
    }    
  }
}

Is there a smarter way to do this? I feel like there is a better way to get this information without doing 11 separate queries. Thank you very much in advance.

Upvotes: 0

Views: 36

Answers (2)

user9940960
user9940960

Reputation: 134

You can put a terms agg query inside another terms query.And if you wanna aggregation for more than one field,you can use composite query.Wish can help you.

Upvotes: 0

Kevin Quinzel
Kevin Quinzel

Reputation: 1428

You were not far from the solution. You have to perform the first aggregation and then an aggregation inside of it. Like this:

GET master/_search 
{ 
    "size": 0, #You want the results from the aggs, the query results can be ignored
    "aggs": { 
        "Console_name": { 
            "terms": { 
                 "field": "console" 
                 "size": 30 #default value is 10
            },
            "aggs":{
                "Game_names":{
                    "terms": { 
                        "field": "games",
                         "size": 30 #default value is 10
                    },
                }
            }
        } 
    }, 
    "query": {  
        "match_all":{} #assuming that you want to work with all the docs in your index
    } 
}

This will bring first the top consoles and, inside them, the top games for each.

Terms by default brings everything in descending order.

Hope this is helpful! :D

Upvotes: 0

Related Questions