GraphQL Search Query Tutorial

The following sections provide examples of Star Wars GraphQL queries and responses.

If you have started the services following the Quick Start guide, you can also try out the queries and modify them as you see fit.

All examples in this section are based on the Star Wars dataset.

Queries

The GraphQL implementation of the Search Service allows you to invoke queries with syntax nearly identical to that of Elasticsearch.

Basic

The most basic search query you can execute is:

Loading...
true
query getWookiees { wookiee_search { max_score hits { score wookiee { id name rdfs_label {value lang} } } } }
{ "data": { "wookiee_search": { "max_score": 1, "hits": [ { "score": 1, "wookiee": { "id": "https://swapi.co/resource/wookiee/13", "name": "Chewbacca", "rdfs_label": [ { "value": "Чүбәкка", "lang": "tt-Cyrl" }, { "value": "Чүбәкка", "lang": "tt" }, { "value": "Чубакка", "lang": "uk" }, { "value": "Чубакка", "lang": "ru" }, { "value": "Τσουμπάκα", "lang": "el" }, { "value": "ชิวแบคคา", "lang": "th" }, { "value": "チューバッカ", "lang": "ja" }, { "value": "丘巴卡", "lang": "zh-Hant" }, { "value": "Chewbacca", "lang": "cs" }, { "value": "Chewbacca", "lang": "cy" }, { "value": "Chewbacca", "lang": "da" }, { "value": "Chewbacca", "lang": "de" }, { "value": "Chewbacca", "lang": "de-CH" }, { "value": "Chewbacca", "lang": "en" }, { "value": "Chewbacca", "lang": "br" }, { "value": "Chewbacca", "lang": "ca" }, { "value": "Chewbacca", "lang": "en-CA" }, { "value": "Chewbacca", "lang": "en-GB" }, { "value": "Chewbacca", "lang": "es" }, { "value": "Chewbacca", "lang": "eu" }, { "value": "Chewbacca", "lang": "fi" }, { "value": "Chewbacca", "lang": "fr" }, { "value": "Chewbacca", "lang": "gl" }, { "value": "Chewbacca", "lang": "ia" }, { "value": "Chewbacca", "lang": "la" }, { "value": "Chewbacca", "lang": "nb" }, { "value": "Chewbacca", "lang": "nl" }, { "value": "Chewbacca", "lang": "oc" }, { "value": "Chewbacca", "lang": "pl" }, { "value": "Chewbacca", "lang": "pt" }, { "value": "Chewbecca", "lang": "it" }, { "value": "Chewbacca", "lang": "pt-BR" }, { "value": "Chewbacca", "lang": "ro" }, { "value": "Chewbacca", "lang": "sco" }, { "value": "Chewbacca", "lang": "sk" }, { "value": "Chewbacca", "lang": "sv" }, { "value": "Chewbacca", "lang": "tr" }, { "value": "Chewbacca", "lang": null }, { "value": "تشوباكا", "lang": "ar" }, { "value": "츄바카", "lang": "ko" }, { "value": "چوباکا", "lang": "fa" }, { "value": "Çubakka", "lang": "az" }, { "value": "טשובאקא", "lang": "yi" }, { "value": "丘百卡", "lang": "zh" }, { "value": "Csubakka", "lang": "hu" }, { "value": "Чубака", "lang": "be" }, { "value": "Чубака", "lang": "be-tarask" }, { "value": "Чубака", "lang": "bg" }, { "value": "Чубака", "lang": "sr" }, { "value": "ჩუბაკა", "lang": "ka" }, { "value": "צ'ובאקה", "lang": "he" } ] } }, { "score": 1, "wookiee": { "id": "https://swapi.co/resource/wookiee/80", "name": "Tarfful", "rdfs_label": [ { "value": "Tarfful", "lang": null } ] } } ] } } }

As you can see, the query response contains all wookiees present in the dataset, their Elasticsearch score, and the requested fields in the sub-selection.

Compound Queries

Compound queries wrap other compound or leaf queries with the purpose of either combining their results and scores, changing their behavior, or switching from query to filter context.

Boolean Queries

The following GraphQL query shows a simple term query that finds all characters with height of 177.

Loading...
true
query character_query { character_search( query: { term: { height: { value: "177" } } } ) { max_score hits { score character { id name height } } } }
{ "data": { "character_search": { "max_score": 1, "hits": [ { "score": 1, "character": { "id": "https://swapi.co/resource/human/25", "name": "Lando Calrissian", "height": "177.0" } } ] } } }

You can mix different query types using Boolean queries. For example, this GraphQL query will find all characters with name “Lando Calrissian” and height of 177:

Loading...
true
query character_query_bool { character_search( query: { bool: { must: [{ match: { name: { query: "Lando Calrissian" } } }, { term: { height: { value: "177" } } }] } } ) { max_score hits { score character { id name height } } } }
{ "data": { "character_search": { "max_score": 8.986293, "hits": [ { "score": 8.986293, "character": { "id": "https://swapi.co/resource/human/25", "name": "Lando Calrissian", "height": "177.0" } } ] } } }

We can make a query to the character index for a name matching "Luke SkywalekS" with fuzziness and fuzzy_transpositions, and we can boost the found results score by 4.0:

Loading...
true
query test { character_search( query: { bool: {must: {match: {name: {query: "Luke SkywalekS" fuzziness: "2" boost: 4.0 fuzzy_transpositions: true } }}} }) { max_score hits { score character { id name } } } }
{ "data": { "character_search": { "max_score": 25.810635, "hits": [ { "score": 25.810635, "character": { "id": "https://swapi.co/resource/human/1", "name": "Luke Skywalker" } }, { "score": 9.838049, "character": { "id": "https://swapi.co/resource/human/43", "name": "Shmi Skywalker" } }, { "score": 9.838049, "character": { "id": "https://swapi.co/resource/human/11", "name": "Anakin Skywalker" } }, { "score": 7.986293, "character": { "id": "https://swapi.co/resource/neimodian/33", "name": "Nute Gunray" } } ] } } }

You can limit the results by using different query types like Match queries, Wildcard queries, or Term queries. For example, the following GraphQL query will return all characters whose type contains “Droi”, or have a birthYear 19BBY, or have name Jek Tono Porkins.

Loading...
true
query qq { character_search( query: { bool: {should: [ {match: {name: {query: "Jek Tono Porkins" boost: 6.0 } } }, {match: {birthYear: {query: "19BBY" } } }, {wildcard: {type: {value: "*Droi*" boost: 8.0 } } } ]} } size: 1000 ) { max_score hits { score character { id name type birthYear } } } }
{ "data": { "character_search": { "max_score": 59.389515, "hits": [ { "score": 59.389515, "character": { "id": "https://swapi.co/resource/human/19", "name": "Jek Tono Porkins", "type": [ "https://swapi.co/vocabulary/Character", "https://swapi.co/vocabulary/Human", "https://swapi.co/vocabulary/Sentient", "https://swapi.co/vocabulary/Mammal" ], "birthYear": null } }, { "score": 8, "character": { "id": "https://swapi.co/resource/droid/23", "name": "IG-88", "type": [ "https://swapi.co/vocabulary/Character", "https://swapi.co/vocabulary/Droid", "https://swapi.co/vocabulary/Sentient", "https://swapi.co/vocabulary/Artificial" ], "birthYear": "15BBY" } }, { "score": 8, "character": { "id": "https://swapi.co/resource/droid/2", "name": "C-3PO", "type": [ "https://swapi.co/vocabulary/Character", "https://swapi.co/vocabulary/Droid", "https://swapi.co/vocabulary/Sentient", "https://swapi.co/vocabulary/Artificial" ], "birthYear": "112BBY" } }, { "score": 8, "character": { "id": "https://swapi.co/resource/droid/3", "name": "R2-D2", "type": [ "https://swapi.co/vocabulary/Character", "https://swapi.co/vocabulary/Droid", "https://swapi.co/vocabulary/Sentient", "https://swapi.co/vocabulary/Artificial" ], "birthYear": "33BBY" } }, { "score": 8, "character": { "id": "https://swapi.co/resource/droid/75", "name": "R4-P17", "type": [ "https://swapi.co/vocabulary/Character", "https://swapi.co/vocabulary/Droid", "https://swapi.co/vocabulary/Sentient", "https://swapi.co/vocabulary/Artificial" ], "birthYear": null } }, { "score": 8, "character": { "id": "https://swapi.co/resource/droid/87", "name": "BB8", "type": [ "https://swapi.co/vocabulary/Character", "https://swapi.co/vocabulary/Droid", "https://swapi.co/vocabulary/Sentient", "https://swapi.co/vocabulary/Artificial" ], "birthYear": null } }, { "score": 8, "character": { "id": "https://swapi.co/resource/droid/8", "name": "R5-D4", "type": [ "https://swapi.co/vocabulary/Character", "https://swapi.co/vocabulary/Droid", "https://swapi.co/vocabulary/Sentient", "https://swapi.co/vocabulary/Artificial" ], "birthYear": null } }, { "score": 2.8678987, "character": { "id": "https://swapi.co/resource/human/5", "name": "Leia Organa", "type": [ "https://swapi.co/vocabulary/Character", "https://swapi.co/vocabulary/Human", "https://swapi.co/vocabulary/Sentient", "https://swapi.co/vocabulary/Mammal" ], "birthYear": "19BBY" } }, { "score": 2.8678987, "character": { "id": "https://swapi.co/resource/human/1", "name": "Luke Skywalker", "type": [ "https://swapi.co/vocabulary/Character", "https://swapi.co/vocabulary/Human", "https://swapi.co/vocabulary/Sentient", "https://swapi.co/vocabulary/Mammal" ], "birthYear": "19BBY" } } ] } } }

Function Score Queries

The function_score allows you to modify the score of documents that are retrieved by a query. This can be useful if, for example, a score function is computationally expensive and it is sufficient to compute the score on a filtered set of documents.

Here is an example where we return all Characters, but boost the results by 5 of those who have either “white”, “blue”, or “pale” skinColor:

Loading...
true
{ character_search(query:{ bool: { must: {match_all:{}} should: { function_score:{ query:{ terms: {skinColor: ["white", "blue", "pale"]}} boost: 5 random_score:{} boost_mode:multiply } } } } size: 20){ total hits{ score character{ id name skinColor } } } }
{ "data": { "character_search": { "total": 87, "hits": [ { "score": 5.585807, "character": { "id": "https://swapi.co/resource/vulptereen/48", "name": "Dud Bolt", "skinColor": [ "blue", "grey" ] } }, { "score": 5.3249793, "character": { "id": "https://swapi.co/resource/toydarian/40", "name": "Watto", "skinColor": [ "blue", "grey" ] } }, { "score": 4.9167557, "character": { "id": "https://swapi.co/resource/cerean/52", "name": "Ki-Adi-Mundi", "skinColor": [ "pale" ] } }, { "score": 4.6883593, "character": { "id": "https://swapi.co/resource/chagrian/59", "name": "Mas Amedda", "skinColor": [ "blue" ] } }, { "score": 4.6049685, "character": { "id": "https://swapi.co/resource/twilek/46", "name": "Ayla Secura", "skinColor": [ "blue" ] } }, { "score": 4.166979, "character": { "id": "https://swapi.co/resource/kaleesh/79", "name": "Grievous", "skinColor": [ "brown", "white" ] } }, { "score": 4.018106, "character": { "id": "https://swapi.co/resource/umbaran/82", "name": "Sly Moore", "skinColor": [ "pale" ] } }, { "score": 3.9804347, "character": { "id": "https://swapi.co/resource/quermian/57", "name": "Yarael Poof", "skinColor": [ "white" ] } }, { "score": 3.904905, "character": { "id": "https://swapi.co/resource/xexto/49", "name": "Gasgano", "skinColor": [ "blue", "white" ] } }, { "score": 2.8095267, "character": { "id": "https://swapi.co/resource/iktotchi/56", "name": "Saesee Tiin", "skinColor": [ "pale" ] } }, { "score": 2.7914903, "character": { "id": "https://swapi.co/resource/human/21", "name": "Palpatine", "skinColor": [ "pale" ] } }, { "score": 2.681255, "character": { "id": "https://swapi.co/resource/aleena/47", "name": "Ratts Tyerell", "skinColor": [ "blue", "grey" ] } }, { "score": 2.6454444, "character": { "id": "https://swapi.co/resource/droid/8", "name": "R5-D4", "skinColor": [ "white", "red" ] } }, { "score": 2.2077322, "character": { "id": "https://swapi.co/resource/human/4", "name": "Darth Vader", "skinColor": [ "white" ] } }, { "score": 1.665283, "character": { "id": "https://swapi.co/resource/droid/3", "name": "R2-D2", "skinColor": [ "blue", "white" ] } }, { "score": 1.0475109, "character": { "id": "https://swapi.co/resource/twilek/45", "name": "Bib Fortuna", "skinColor": [ "pale" ] } }, { "score": 1.0467557, "character": { "id": "https://swapi.co/resource/togruta/78", "name": "Shaak Ti", "skinColor": [ "blue", "white", "red" ] } }, { "score": 1, "character": { "id": "https://swapi.co/resource/sullustan/31", "name": "Nien Nunb", "skinColor": [ "grey" ] } }, { "score": 1, "character": { "id": "https://swapi.co/resource/kaminoan/73", "name": "Taun We", "skinColor": [ "grey" ] } }, { "score": 1, "character": { "id": "https://swapi.co/resource/kaminoan/72", "name": "Lama Su", "skinColor": [ "grey" ] } } ] } } }

Term-level Queries

You can use term-level queries to find documents based on precise values in structured data.

Types of Term-level Queries

Fuzzy queries and fuzziness parameter in other queries are also supported. They allow finding results containing terms similar to the search terms. For example, the following fuzzy query will result in finding characters with green eyeColor although the search term contains switched, missing, or extra characters:

Loading...
true
query fuzzy { character_search( query: { fuzzy: { eyeColor: { value: "brene" fuzziness: "2" transpositions: true } } } size: 1000 ) { max_score hits { score character { name eyeColor } } } }
{ "data": { "character_search": { "max_score": 2.4455783, "hits": [ { "score": 2.4455783, "character": { "name": "Grievous", "eyeColor": [ "yellow", "green" ] } } ] } } }

Exists queries return documents that contain an indexed value for a field. For example, the following GraphQL query will return only Characters that have indexed value for cybernetics. Note that cybernetics is property that belongs to the Human subclass, and not Character, so in the qeury input we refer to it as Human_cybernetics and in the request we get it using inline fragment ``… on Human ``:

Loading...
true
{ character_search(query:{ exists:{ field: Human_cybernetics, boost: 5 } }){ hits{ score character{ id name ... on Human { cybernetics } } } } }
{ "data": { "character_search": { "hits": [ { "score": 5, "character": { "id": "https://swapi.co/resource/human/4", "name": "Darth Vader", "cybernetics": [ "Cybernetic right arm", "prosthetic arms and legs", "life-support system" ] } }, { "score": 5, "character": { "id": "https://swapi.co/resource/human/1", "name": "Luke Skywalker", "cybernetics": [ "Prosthetic right hand" ] } }, { "score": 5, "character": { "id": "https://swapi.co/resource/human/11", "name": "Anakin Skywalker", "cybernetics": [ "Cybernetic right arm" ] } } ] } } }

Term queries returns documents that contain an exact term in a provided field.

You can use the term query to find documents based on a precise value such as a price, a product ID, or a username.

Loading...
true
{ character_search( query: { term: { skinColor: { value: "white" } } } ) { total hits { score character { id name skinColor } } } }
{ "data": { "character_search": { "total": 7, "hits": [ { "score": 2.6072772, "character": { "id": "https://swapi.co/resource/kaleesh/79", "name": "Grievous", "skinColor": [ "brown", "white" ] } }, { "score": 2.6072772, "character": { "id": "https://swapi.co/resource/human/4", "name": "Darth Vader", "skinColor": [ "white" ] } }, { "score": 2.6072772, "character": { "id": "https://swapi.co/resource/droid/3", "name": "R2-D2", "skinColor": [ "blue", "white" ] } }, { "score": 2.6072772, "character": { "id": "https://swapi.co/resource/droid/8", "name": "R5-D4", "skinColor": [ "white", "red" ] } }, { "score": 2.6072772, "character": { "id": "https://swapi.co/resource/xexto/49", "name": "Gasgano", "skinColor": [ "blue", "white" ] } }, { "score": 2.6072772, "character": { "id": "https://swapi.co/resource/togruta/78", "name": "Shaak Ti", "skinColor": [ "blue", "white", "red" ] } }, { "score": 2.6072772, "character": { "id": "https://swapi.co/resource/quermian/57", "name": "Yarael Poof", "skinColor": [ "white" ] } } ] } } }

Terms queries are the same as the term query, except you can search for multiple values.

Loading...
true
{ character_search( query:{ terms: { skinColor:["white", "blue"] } } size: 15 ){ total hits{ score character{ id name skinColor } } } }
{ "data": { "character_search": { "total": 12, "hits": [ { "score": 1, "character": { "id": "https://swapi.co/resource/kaleesh/79", "name": "Grievous", "skinColor": [ "brown", "white" ] } }, { "score": 1, "character": { "id": "https://swapi.co/resource/twilek/46", "name": "Ayla Secura", "skinColor": [ "blue" ] } }, { "score": 1, "character": { "id": "https://swapi.co/resource/human/4", "name": "Darth Vader", "skinColor": [ "white" ] } }, { "score": 1, "character": { "id": "https://swapi.co/resource/droid/3", "name": "R2-D2", "skinColor": [ "blue", "white" ] } }, { "score": 1, "character": { "id": "https://swapi.co/resource/droid/8", "name": "R5-D4", "skinColor": [ "white", "red" ] } }, { "score": 1, "character": { "id": "https://swapi.co/resource/aleena/47", "name": "Ratts Tyerell", "skinColor": [ "blue", "grey" ] } }, { "score": 1, "character": { "id": "https://swapi.co/resource/xexto/49", "name": "Gasgano", "skinColor": [ "blue", "white" ] } }, { "score": 1, "character": { "id": "https://swapi.co/resource/togruta/78", "name": "Shaak Ti", "skinColor": [ "blue", "white", "red" ] } }, { "score": 1, "character": { "id": "https://swapi.co/resource/toydarian/40", "name": "Watto", "skinColor": [ "blue", "grey" ] } }, { "score": 1, "character": { "id": "https://swapi.co/resource/quermian/57", "name": "Yarael Poof", "skinColor": [ "white" ] } }, { "score": 1, "character": { "id": "https://swapi.co/resource/vulptereen/48", "name": "Dud Bolt", "skinColor": [ "blue", "grey" ] } }, { "score": 1, "character": { "id": "https://swapi.co/resource/chagrian/59", "name": "Mas Amedda", "skinColor": [ "blue" ] } } ] } } }

Match_all Query

You can also use Match_all queries to match all documents from a given indexed object type. For example, the following GraphQL query will return all indexed Films (max 1,000) with their score boosted to 5.0:

Loading...
true
query allFilms { film_search( query: { match_all: {boost: 5.0} } size:1000 ) { hits { score film { id name } } } }
{ "data": { "film_search": { "hits": [ { "score": 5, "film": { "id": "https://swapi.co/resource/film/4", "name": "Star Wars: Episode I – The Phantom Menace" } }, { "score": 5, "film": { "id": "https://swapi.co/resource/film/5", "name": "Star Wars: Episode II – Attack of the Clones" } }, { "score": 5, "film": { "id": "https://swapi.co/resource/film/6", "name": "Star Wars: Episode III – Revenge of the Sith" } }, { "score": 5, "film": { "id": "https://swapi.co/resource/film/2", "name": "The Empire Strikes Back" } }, { "score": 5, "film": { "id": "https://swapi.co/resource/film/3", "name": "Return of the Jedi" } }, { "score": 5, "film": { "id": "https://swapi.co/resource/film/1", "name": "Star Wars" } }, { "score": 5, "film": { "id": "https://swapi.co/resource/film/7", "name": "Star Wars: The Force Awakens" } } ] } } }

Boost

Some matching results can be boosted using the Elasticsearch boost parameter. For example, the query below will return all characters with type Human or with height over 190. The score of the Human characters will be boosted by 5.0 and the score of the characters with height will be boosted by 10.0. The score of the characters that are both Human and taller than 190 will be the highest, followed by the taller non-Human characters, followed by the Human characters.

Loading...
true
query boost { character_search( query: { bool: {should: [ {match: {type: {query: "https://swapi.co/vocabulary/Human" boost: 5.0 } } }, {range: {height: {gt: "190" boost: 10.0 } } } ]} } size: 4 ) { max_score hits { score character { name type height } } } }
{ "data": { "character_search": { "max_score": 15.962927, "hits": [ { "score": 15.962927, "character": { "name": "Darth Vader", "type": [ "https://swapi.co/vocabulary/Character", "https://swapi.co/vocabulary/Human", "https://swapi.co/vocabulary/Sentient", "https://swapi.co/vocabulary/Mammal" ], "height": "202.0" } }, { "score": 15.962927, "character": { "name": "Qui-Gon Jinn", "type": [ "https://swapi.co/vocabulary/Character", "https://swapi.co/vocabulary/Human", "https://swapi.co/vocabulary/Sentient", "https://swapi.co/vocabulary/Mammal" ], "height": "193.0" } }, { "score": 15.962927, "character": { "name": "Bail Prestor Organa", "type": [ "https://swapi.co/vocabulary/Character", "https://swapi.co/vocabulary/Human", "https://swapi.co/vocabulary/Sentient", "https://swapi.co/vocabulary/Mammal" ], "height": "191.0" } }, { "score": 15.962927, "character": { "name": "Dooku", "type": [ "https://swapi.co/vocabulary/Character", "https://swapi.co/vocabulary/Human", "https://swapi.co/vocabulary/Sentient", "https://swapi.co/vocabulary/Mammal" ], "height": "193.0" } } ] } } }

Sorting

The following GraphQL query shows how to apply results sorting on the height field in descending order:

Loading...
true
query character_sorting { character_search( sort: { height: { order: desc } } ) { max_score hits { score character { id name height } } } }
{ "data": { "character_search": { "max_score": 1, "hits": [ { "score": 1, "character": { "id": "https://swapi.co/resource/quermian/57", "name": "Yarael Poof", "height": "264.0" } }, { "score": 1, "character": { "id": "https://swapi.co/resource/wookiee/80", "name": "Tarfful", "height": "234.0" } }, { "score": 1, "character": { "id": "https://swapi.co/resource/kaminoan/72", "name": "Lama Su", "height": "229.0" } }, { "score": 1, "character": { "id": "https://swapi.co/resource/wookiee/13", "name": "Chewbacca", "height": "228.0" } }, { "score": 1, "character": { "id": "https://swapi.co/resource/gungan/37", "name": "Roos Tarpals", "height": "224.0" } }, { "score": 1, "character": { "id": "https://swapi.co/resource/kaleesh/79", "name": "Grievous", "height": "216.0" } }, { "score": 1, "character": { "id": "https://swapi.co/resource/kaminoan/73", "name": "Taun We", "height": "213.0" } }, { "score": 1, "character": { "id": "https://swapi.co/resource/gungan/38", "name": "Rugor Nass", "height": "206.0" } }, { "score": 1, "character": { "id": "https://swapi.co/resource/pauan/83", "name": "Tion Medon", "height": "206.0" } }, { "score": 1, "character": { "id": "https://swapi.co/resource/human/4", "name": "Darth Vader", "height": "202.0" } } ] } } }

Currently, the following sorting options are supported:

  • order

  • mode

  • missing

  • numeric_type

See more about Elasticsearch sorting here.

Paging

This GraphQL query shows how to apply paging to the response. The size argument defines the page size, while from defines the amount of records to skip:

Loading...
true
query character_query { character_search( sort: { height: { order: desc } } size: 6 from: 10 ) { max_score hits { score character { id name height } } } }
{ "data": { "character_search": { "max_score": 1, "hits": [ { "score": 1, "character": { "id": "https://swapi.co/resource/droid/23", "name": "IG-88", "height": "200.0" } }, { "score": 1, "character": { "id": "https://swapi.co/resource/cerean/52", "name": "Ki-Adi-Mundi", "height": "198.0" } }, { "score": 1, "character": { "id": "https://swapi.co/resource/besalisk/71", "name": "Dexter Jettster", "height": "198.0" } }, { "score": 1, "character": { "id": "https://swapi.co/resource/gungan/36", "name": "Jar Jar Binks", "height": "196.0" } }, { "score": 1, "character": { "id": "https://swapi.co/resource/nautolan/53", "name": "Kit Fisto", "height": "196.0" } }, { "score": 1, "character": { "id": "https://swapi.co/resource/chagrian/59", "name": "Mas Amedda", "height": "196.0" } } ] } } }

Note

By default, the size of the response is limited to 10.

Aggregations

Elasticsearch aggregations summarize data as metrics, statistics, or other analytics. The Ontotext Platform supports two aggregation types: metrics and bucket aggregations, as well as sub-aggregations between them. Let’s have a look at them in more detail.

Metrics Aggregations

Metrics aggregations compute metrics based on values extracted in one way or another from the documents that are being aggregated. The values are usually extracted from the fields of the document using the field data. We will take a look at some of them below.

Avg aggregations are single-value metrics aggregations that compute the average of numeric values that are extracted from the aggregated documents. This query shows an aggregation over the average height of Characters.

Loading...
true
{ character_search ( aggs: [ { name: "avg01" value: { avg: { field: "height" } } } { name: "avg01missing" value: { avg: { field: "height" missing: 50 } } } ] ) { aggregations } }
{ "data": { "character_search": { "aggregations": { "avg01missing": { "value": 165.7816091954023 }, "avg01": { "value": 174.35802469135803 } } } } }

Cardinality aggregations are single-value metrics aggregation that calculate an approximate count of distinct values. This query aggregates the cardinality of different Character fields.

Loading...
true
{ character_search ( aggs: [ { name: "homeworld nested" value: { nested: { path: "homeworld" } aggs: { name: "homeworld cardinality" value: { cardinality: { field: "homeworld.id" precision_threshold: 10 } } } } } { name: "gender cardinality" value: { cardinality: { field: "gender" missing: "N/A" } } } ] ) { aggregations } }
{ "data": { "character_search": { "aggregations": { "gender cardinality": { "value": 4 }, "homeworld nested": { "doc_count": 87, "homeworld cardinality": { "value": 54 } } } } } }

Max aggregations are single-value metrics aggregation that keeps track and returns the maximum value among the numeric values extracted from the aggregated documents. This query aggregates max values of different Character fields.

Loading...
true
{ character_search ( aggs: [ { name: "height max" value: { max: { field: "height" } } } { name: "height max missing" value: { max: { field: "height" missing: 1000 } } } { name: "height max script" value: { max: { field: "height" script: { lang: "painless" source: "if (_value != null) return _value * params.multiplier; return -1;" params: {multiplier: 3} } } } } ] ) { aggregations } }
{ "data": { "character_search": { "aggregations": { "height max script": { "value": 792.0 }, "height max": { "value": 264.0 }, "height max missing": { "value": 1000.0 } } } } }

Min aggregations are single-value metrics aggregations that keep track and return the minimum value among numeric values extracted from the aggregated documents. This query aggregates min values of different Human fields.

Loading...
true
{ character_search ( query:{ term: { type: { value: "https://swapi.co/vocabulary/Human" } } } aggs: [ { name: "height min" value: { min: { field: "height" } } } { name: "height min missing" value: { min: { field: "height" missing: 10 } } } { name: "height min script" value: { min: { field: "height" script: { lang: "painless" source: "if (_value != null) return _value * params.multiplier; return 10000;" params: {multiplier: 3} } } } } ] ) { aggregations } }
{ "data": { "character_search": { "aggregations": { "height min": { "value": 150.0 }, "height min missing": { "value": 10.0 }, "height min script": { "value": 450.0 } } } } }

Percentile ranks aggregations are multi-value metrics aggregations that calculate one or more percentile ranks over numeric values extracted from the aggregated documents. This query aggregates the percentile ranks for averageHeight of Species.

Loading...
true
{ species_search ( aggs: [ { name: "averageHeight percentile ranks" value: { percentile_ranks: { field: "averageHeight" values: [70, 100, 200] } } } ] ) { aggregations } }
{ "data": { "species_search": { "aggregations": { "averageHeight percentile ranks": { "values": { "70.0": 2.2448979591836733, "100.0": 11.428571428571429, "200.0": 85.71428571428571 } } } } } }

Percentiles aggregations are multi-value metrics aggregations that calculate one or more percentiles over numeric values extracted from the aggregated documents. This query aggregates the percentiles for Character mass with different Elasticsearch options: missing value, keyed response, HDR histogram, compression.

Loading...
true
{ character_search ( aggs: [ { name: "mass percentile ranks" value: { percentiles: { field: "mass" } } } { name: "mass percentile ranks missing" value: { percentiles: { field: "mass" missing: 300 } } } { name: "mass percentile ranks not keyed" value: { percentiles: { field: "mass" keyed: false } } } { name: "mass percentile ranks hdr" value: { percentiles: { field: "mass" hdr: { number_of_significant_value_digits: 1 # returned value accuracy is lowered by this , so 99.9 percentile gets higher than the max mass value } percents: [ 95, 99, 99.9 ] } } } { name: "mass percentile ranks compression" value: { percentiles: { field: "mass" tdigest: { compression: 101 } } } } ] ) { aggregations } }
{ "data": { "character_search": { "aggregations": { "mass percentile ranks compression": { "values": { "1.0": 15.18, "5.0": 25.400000000000002, "25.0": 55.25, "50.0": 79.0, "75.0": 84.75, "95.0": 138.2, "99.0": 1250.089999999996 } }, "mass percentile ranks hdr": { "values": { "95.0": 143.5, "99.0": 159.5, "99.9": 1407.5 } }, "mass percentile ranks not keyed": { "values": [ { "key": 1.0, "value": 15.18 }, { "key": 5.0, "value": 25.400000000000002 }, { "key": 25.0, "value": 55.25 }, { "key": 50.0, "value": 79.0 }, { "key": 75.0, "value": 84.75 }, { "key": 95.0, "value": 138.2 }, { "key": 99.0, "value": 1250.089999999996 } ] }, "mass percentile ranks": { "values": { "1.0": 15.18, "5.0": 25.400000000000002, "25.0": 55.25, "50.0": 79.0, "75.0": 84.75, "95.0": 138.2, "99.0": 1250.089999999996 } }, "mass percentile ranks missing": { "values": { "1.0": 15.739999999999998, "5.0": 32.0, "25.0": 75.0, "50.0": 84.0, "75.0": 300.0, "95.0": 300.0, "99.0": 966.5399999999952 } } } } } }

Stats aggregations are multi-value metrics aggregations that compute stats over numeric values extracted from the aggregated documents. This query aggregates stats for Character height and mass.

Loading...
true
{ character_search ( aggs: [ { name: "character height stats" value: { stats: { field: "height" } } } { name: "character height stats missing" value: { stats: { field: "height" missing: 100 } } } { name: "character mass stats" value: { stats: { field: "mass" } } } ] ) { aggregations } }
{ "data": { "character_search": { "aggregations": { "character mass stats": { "count": 59, "min": 15.0, "max": 1358.0, "avg": 97.30508474576271, "sum": 5741 }, "character height stats missing": { "count": 87, "min": 66.0, "max": 264.0, "avg": 169.22988505747125, "sum": 14723.0 }, "character height stats": { "count": 81, "min": 66.0, "max": 264.0, "avg": 174.35802469135803, "sum": 14123.0 } } } } }

String stats aggregations are multi-value metrics aggregations that compute statistics over string values extracted from the aggregated documents. This query aggregates string stats for Character gender by field, by script, using missing, with show_distribution.

Loading...
true
{ character_search ( aggs: [ { name: "character gender string_stats" value: { string_stats: { field: "gender" } } } { name: "character gender string_stats missing" value: { string_stats: { field: "gender" missing: "droiddddddddddddddddd" } } } { name: "character gender string_stats script" value: { string_stats: { script: { source: "if (doc.gender.size() != 0) doc.gender.value" } } } } { name: "character gender string_stats with distribution" value: { string_stats: { field: "gender" show_distribution: true } } } ] ) { aggregations } }
{ "data": { "character_search": { "aggregations": { "character gender string_stats script": { "count": 82, "min_length": 4, "max_length": 13, "avg_length": 4.573170731707317, "entropy": 2.3601750877098007 }, "character gender string_stats with distribution": { "count": 82, "min_length": 4, "max_length": 13, "avg_length": 4.573170731707317, "entropy": 2.3601750877098007, "distribution": { "e": 0.272, "a": 0.21866666666666668, "m": 0.21866666666666668, "l": 0.216, "f": 0.050666666666666665, "r": 0.005333333333333333, "h": 0.005333333333333333, "p": 0.0026666666666666666, "t": 0.0026666666666666666, "d": 0.0026666666666666666, "i": 0.0026666666666666666, "o": 0.0026666666666666666 } }, "character gender string_stats": { "count": 82, "min_length": 4, "max_length": 13, "avg_length": 4.573170731707317, "entropy": 2.3601750877098007 }, "character gender string_stats missing": { "count": 87, "min_length": 4, "max_length": 21, "avg_length": 5.517241379310345, "entropy": 2.73533906779877 } } } } }

Sum aggregations are single-value metrics aggregations that sum up numeric values that are extracted from the aggregated documents. This query aggregates sum for Character height and mass.

Loading...
true
{ character_search ( aggs: [ { name: "character height sum" value: { sum: { field: "height" missing: 100 } } } { name: "character mass sum" value: { sum: { field: "mass" } } } ] ) { aggregations } }
{ "data": { "character_search": { "aggregations": { "character mass sum": { "value": 5741 }, "character height sum": { "value": 14723.0 } } } } }

Top metrics aggregations select metrics from the document with the largest or smallest “sort” value. This query aggregates a character’s height for top mass and height for top _score for Characters with eyeColor matching “blue”, “gray”, “yellow”, or “green”.

Loading...
true
{ character_search ( query: { terms: { eyeColor: ["blue", "gray", "yellow", "green"] } } aggs: [ { name: "character's height for top mass" value: { top_metrics: { metrics: [ {field: "height"} {field: "mass"} ] sort: {mass: desc} } } } ] size: 2 ) { aggregations hits{ score character{ id name height mass eyeColor } } } }
{ "data": { "character_search": { "aggregations": { "character's height for top mass": { "top": [ { "sort": [ 159 ], "metrics": { "height": 216, "mass": 159 } } ] } }, "hits": [ { "score": 1, "character": { "id": "https://swapi.co/resource/kaleesh/79", "name": "Grievous", "height": "216.0", "mass": "159.0", "eyeColor": [ "yellow", "green" ] } }, { "score": 1, "character": { "id": "https://swapi.co/resource/clawdite/70", "name": "Zam Wesell", "height": "168.0", "mass": "55.0", "eyeColor": [ "yellow" ] } } ] } } }

Value_count aggregations are single-value metrics aggregations that count the number of values that are extracted from the aggregated documents. This query aggregates the value count of the residents of a planet (requires nestingLevel >=1).

Loading...
true
{ planet_search ( aggs: [ { name: "planet" value: { terms:{ field: "id" } aggs:{ name: "residents stats" value: { nested: { path: "resident" } aggs:{ name: "residentStats" value: { value_count: { field: "resident.id" } } } } } } } ] ) { aggregations } }
{ "data": { "planet_search": { "aggregations": { "planet": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 51, "buckets": [ { "key": "https://swapi.co/resource/planet/1", "doc_count": 1, "residents stats": { "doc_count": 10, "residentStats": { "value": 10 } } }, { "key": "https://swapi.co/resource/planet/10", "doc_count": 1, "residents stats": { "doc_count": 3, "residentStats": { "value": 3 } } }, { "key": "https://swapi.co/resource/planet/11", "doc_count": 1, "residents stats": { "doc_count": 1, "residentStats": { "value": 1 } } }, { "key": "https://swapi.co/resource/planet/12", "doc_count": 1, "residents stats": { "doc_count": 1, "residentStats": { "value": 1 } } }, { "key": "https://swapi.co/resource/planet/13", "doc_count": 1, "residents stats": { "doc_count": 0, "residentStats": { "value": 0 } } }, { "key": "https://swapi.co/resource/planet/14", "doc_count": 1, "residents stats": { "doc_count": 2, "residentStats": { "value": 2 } } }, { "key": "https://swapi.co/resource/planet/15", "doc_count": 1, "residents stats": { "doc_count": 0, "residentStats": { "value": 0 } } }, { "key": "https://swapi.co/resource/planet/16", "doc_count": 1, "residents stats": { "doc_count": 0, "residentStats": { "value": 0 } } }, { "key": "https://swapi.co/resource/planet/17", "doc_count": 1, "residents stats": { "doc_count": 0, "residentStats": { "value": 0 } } }, { "key": "https://swapi.co/resource/planet/18", "doc_count": 1, "residents stats": { "doc_count": 1, "residentStats": { "value": 1 } } } ] } } } } }

Weighted avg aggregations are single-value metrics aggregations that compute the weighted average of numeric values that are extracted from the aggregated documents. This query aggregates the weighted average for Film boxOffice weighted by cost.

Loading...
true
{ film_search ( aggs: [ { name: "film" value: { terms:{ field: "id" } aggs:[ { name: "boxOffice wighted by cost" value: { weighted_avg: { value: { field: "boxOffice" } weight: { field: "cost" } } } } { name: "boxOffice wighted by cost with missing" value: { weighted_avg: { value: { field: "boxOffice" missing: "333" } weight: { field: "cost" missing: "1" } value_type: "double" } } } ] } } ] ) { aggregations } }
{ "data": { "film_search": { "aggregations": { "film": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "https://swapi.co/resource/film/1", "doc_count": 1, "boxOffice wighted by cost": { "value": 7.75512064E8 }, "boxOffice wighted by cost with missing": { "value": 7.75512064E8 } }, { "key": "https://swapi.co/resource/film/2", "doc_count": 1, "boxOffice wighted by cost": { "value": 5.47879454E8 }, "boxOffice wighted by cost with missing": { "value": 5.47879454E8 } }, { "key": "https://swapi.co/resource/film/3", "doc_count": 1, "boxOffice wighted by cost": { "value": null }, "boxOffice wighted by cost with missing": { "value": 4.751E8 } }, { "key": "https://swapi.co/resource/film/4", "doc_count": 1, "boxOffice wighted by cost": { "value": 1.027082707E9 }, "boxOffice wighted by cost with missing": { "value": 1.027082707E9 } }, { "key": "https://swapi.co/resource/film/5", "doc_count": 1, "boxOffice wighted by cost": { "value": 6.49436358E8 }, "boxOffice wighted by cost with missing": { "value": 6.49436358E8 } }, { "key": "https://swapi.co/resource/film/6", "doc_count": 1, "boxOffice wighted by cost": { "value": null }, "boxOffice wighted by cost with missing": { "value": 8.50035635E8 } }, { "key": "https://swapi.co/resource/film/7", "doc_count": 1, "boxOffice wighted by cost": { "value": 1.23017325E8 }, "boxOffice wighted by cost with missing": { "value": 1.23017325E8 } } ] } } } } }

Bucket Aggregations

Bucket aggregations create buckets of documents. Depending on the aggregation type, each bucket is associated with a criterion that determines whether or not a document in the current context falls into it. Bucket aggregations also compute and return the number of documents that fell into each bucket. Let’s take a look at some of them below.

Date range aggregations are range aggregations dedicated for date values. The following GraphQL query shows the bucket aggregation for awardRecognition objects over awardDate field.

Loading...
true
{ awardRecognition_search ( aggs: { name: "awardDate_aggs" value: { date_range: { field: "awardDate" format: "yyyy-MM-dd" ranges: [ {to: "now-30y/y"} {from: "now-30y/y", to:"now-20y/y"} {from: "now-20y/y", to:"now-10y/y"} {from: "now-10y/y"} ] } } } ) { aggregations } }
{ "data": { "awardRecognition_search": { "aggregations": { "awardDate_aggs": { "buckets": [ { "key": "*-1991-01-01", "to": 6.62688E11, "to_as_string": "1991-01-01", "doc_count": 112 }, { "key": "1991-01-01-2001-01-01", "from": 6.62688E11, "from_as_string": "1991-01-01", "to": 9.783072E11, "to_as_string": "2001-01-01", "doc_count": 24 }, { "key": "2001-01-01-2011-01-01", "from": 9.783072E11, "from_as_string": "2001-01-01", "to": 1.29384E12, "to_as_string": "2011-01-01", "doc_count": 31 }, { "key": "2011-01-01-*", "from": 1.29384E12, "from_as_string": "2011-01-01", "doc_count": 31 } ] } } } } }

Filter aggregations define a single bucket of all the documents in the current document set context that match a specified filter. This query shows an aggregation that will return the average mass of characters with height of 183.0.

Loading...
true
{ character_search ( aggs: { name: "filter" value: { filter: { term: {height: {value: "183.0"}} } aggs:[ { name: "avg_mass" value: {avg: {field: "mass"}} } ] } } ) { aggregations } }
{ "data": { "character_search": { "aggregations": { "filter": { "doc_count": 7, "avg_mass": { "value": 80.3 } } } } } }

Missing aggregations are field data based single bucket aggregations that create a bucket of all documents in the current document set context that are missing a field value. This query shows an aggregation that will return the average height of characters without mass.

Loading...
true
{ character_search ( aggs: { name: "missing_mass" value: { missing: { field: "mass"} aggs: { name: "avg_height" value: {avg: {field: "height"}} } } } ) { aggregations } }
{ "data": { "character_search": { "aggregations": { "missing_mass": { "doc_count": 28, "avg_height": { "value": 175.27272727272728 } } } } } }

Nested aggregations are special single bucket aggregations that enable aggregating nested documents. This query will return the string_stats location.type for film/4.

Loading...
true
{ film_search ( query: { terms: {id: ["https://swapi.co/resource/film/4"]} } aggs: { name: "location_min_type" value: { nested: { path: "location" } aggs: { name: "min_type" value: { string_stats: {field: "location.type"} } } } } size: 100 ) { aggregations hits{ film{ id name location { id type } } } } }
{ "data": { "film_search": { "aggregations": { "location_min_type": { "doc_count": 4, "min_type": { "count": 4, "min_length": 35, "max_length": 36, "avg_length": 35.75, "entropy": 4.128295748933657 } } }, "hits": [ { "film": { "id": "https://swapi.co/resource/film/4", "name": "Star Wars: Episode I – The Phantom Menace", "location": [ { "id": "http://www.wikidata.org/entity/Q19835", "type": [ "https://swapi.co/vocabulary/Location" ] }, { "id": "http://www.wikidata.org/entity/Q5049457", "type": [ "https://swapi.co/vocabulary/Location" ] }, { "id": "http://www.wikidata.org/entity/Q948", "type": [ "https://swapi.co/vocabulary/Country" ] }, { "id": "http://www.wikidata.org/entity/Q327983", "type": [ "https://swapi.co/vocabulary/Location" ] } ] } } ] } } }

Range aggregations are multi-bucket value source based aggregations that enable you to define a set of ranges, each representing a bucket. The next query shows an aggregation for characters with height: under 170, from 170 to 190, from 190 to 200, 200 and above.

Loading...
true
{ character_search ( aggs: { name: "height_ranges" value: { range: { field: "height" ranges: [ {to: 170} {from: 170, to:190} {from: 190, to:200} {from: 200} ] } } } ) { aggregations } }
{ "data": { "character_search": { "aggregations": { "height_ranges": { "buckets": [ { "key": "*-170.0", "to": 170, "doc_count": 23 }, { "key": "170.0-190.0", "from": 170, "to": 190, "doc_count": 35 }, { "key": "190.0-200.0", "from": 190, "to": 200, "doc_count": 12 }, { "key": "200.0-*", "from": 200, "doc_count": 11 } ] } } } } }

Terms aggregations are multi-bucket value source based aggregations where buckets are dynamically built, one per unique value. This query shows an aggregation over homeworld with a limit of 5 groups with default sorting, with count in descending order.

Loading...
true
{ character_search ( aggs: { name: "terms1" value: { nested: { path: "homeworld" } aggs: { name: "terms1" value: { terms: { field: "homeworld.id" size: 5 show_term_doc_count_error: true } } } } } ) { aggregations } }
{ "data": { "character_search": { "aggregations": { "terms1": { "doc_count": 87, "terms1": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 50, "buckets": [ { "key": "https://swapi.co/resource/planet/8", "doc_count": 11, "doc_count_error_upper_bound": 0 }, { "key": "https://swapi.co/resource/planet/1", "doc_count": 10, "doc_count_error_upper_bound": 0 }, { "key": "https://swapi.co/resource/planet/28", "doc_count": 10, "doc_count_error_upper_bound": 0 }, { "key": "https://swapi.co/resource/planet/10", "doc_count": 3, "doc_count_error_upper_bound": 0 }, { "key": "https://swapi.co/resource/planet/2", "doc_count": 3, "doc_count_error_upper_bound": 0 } ] } } } } } }

This is another example of terms aggregation over height sorted by the count of the aggregation in ascending order.

Loading...
true
{ character_search ( aggs: { name: "terms2" value: { terms: { field: "height" order: { _count: "desc" } size: 16 shard_size: 5 } } } size: 100 ) { aggregations } }
{ "data": { "character_search": { "aggregations": { "terms2": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 29, "buckets": [ { "key": 183.0, "doc_count": 7 }, { "key": 180.0, "doc_count": 5 }, { "key": 188.0, "doc_count": 5 }, { "key": 170.0, "doc_count": 4 }, { "key": 178.0, "doc_count": 4 }, { "key": 165.0, "doc_count": 3 }, { "key": 175.0, "doc_count": 3 }, { "key": 191.0, "doc_count": 3 }, { "key": 193.0, "doc_count": 3 }, { "key": 196.0, "doc_count": 3 }, { "key": 96.0, "doc_count": 2 }, { "key": 150.0, "doc_count": 2 }, { "key": 163.0, "doc_count": 2 }, { "key": 167.0, "doc_count": 2 }, { "key": 198.0, "doc_count": 2 }, { "key": 206.0, "doc_count": 2 } ] } } } } }

Another terms aggregation over gender excluding values that match the pattern fem.*.

Loading...
true
{character_search ( aggs: { name: "terms2" value: { terms: { field: "gender" size: 15 exclude: "fem.*" } } } size: 100 ) { aggregations } }
{ "data": { "character_search": { "aggregations": { "terms2": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "male", "doc_count": 62 }, { "key": "hermaphrodite", "doc_count": 1 } ] } } } } }

And a final terms aggregation query over root object bucket per type, stats for height, mass, diameter, and length.

Loading...
true
{ root_search ( aggs: { name: "rootTerms" value: { terms: { field: "type" size: 19 show_term_doc_count_error: true } aggs: [ { name: "height_stats" value: {stats: {field: "height"}} } { name: "mass_stats" value: {stats: {field: "mass"}} } { name: "diameter_max" value: {max: {field: "diameter"}} } { name: "length_max" value: {max: {field: "length"}} } ] } } ) { aggregations } }
{ "data": { "root_search": { "aggregations": { "rootTerms": { "doc_count_error_upper_bound": 1, "sum_other_doc_count": 54, "buckets": [ { "key": "https://swapi.co/vocabulary/FilmRole", "doc_count": 345, "doc_count_error_upper_bound": 1, "height_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "mass_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "length_max": { "value": null }, "diameter_max": { "value": null } }, { "key": "https://swapi.co/vocabulary/AwardRecognition", "doc_count": 198, "doc_count_error_upper_bound": 1, "height_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "mass_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "length_max": { "value": null }, "diameter_max": { "value": null } }, { "key": "https://swapi.co/vocabulary/Location", "doc_count": 195, "doc_count_error_upper_bound": 1, "height_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "mass_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "length_max": { "value": null }, "diameter_max": { "value": null } }, { "key": "https://swapi.co/vocabulary/Character", "doc_count": 138, "doc_count_error_upper_bound": 0, "height_stats": { "count": 126, "min": 66.0, "max": 264.0, "avg": 173.88095238095238, "sum": 21909.0 }, "mass_stats": { "count": 91, "min": 15.0, "max": 1358.0, "avg": 91.70989010989011, "sum": 8345.6 }, "length_max": { "value": null }, "diameter_max": { "value": null } }, { "key": "https://swapi.co/vocabulary/Sentient", "doc_count": 138, "doc_count_error_upper_bound": 0, "height_stats": { "count": 126, "min": 66.0, "max": 264.0, "avg": 173.88095238095238, "sum": 21909.0 }, "mass_stats": { "count": 91, "min": 15.0, "max": 1358.0, "avg": 91.70989010989011, "sum": 8345.6 }, "length_max": { "value": null }, "diameter_max": { "value": null } }, { "key": "https://swapi.co/vocabulary/Mammal", "doc_count": 101, "doc_count_error_upper_bound": 0, "height_stats": { "count": 91, "min": 66.0, "max": 264.0, "avg": 176.56043956043956, "sum": 16067.0 }, "mass_stats": { "count": 64, "min": 17.0, "max": 136.0, "avg": 77.946875, "sum": 4988.6 }, "length_max": { "value": null }, "diameter_max": { "value": null } }, { "key": "https://swapi.co/vocabulary/Human", "doc_count": 76, "doc_count_error_upper_bound": 0, "height_stats": { "count": 66, "min": 150.0, "max": 202.0, "avg": 177.03030303030303, "sum": 11684.0 }, "mass_stats": { "count": 44, "min": 45.0, "max": 136.0, "avg": 82.78181818181818, "sum": 3642.4 }, "length_max": { "value": null }, "diameter_max": { "value": null } }, { "key": "https://swapi.co/vocabulary/Award", "doc_count": 62, "doc_count_error_upper_bound": 1, "height_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "mass_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "length_max": { "value": null }, "diameter_max": { "value": null } }, { "key": "https://swapi.co/vocabulary/Country", "doc_count": 41, "doc_count_error_upper_bound": 1, "height_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "mass_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "length_max": { "value": null }, "diameter_max": { "value": null } }, { "key": "https://swapi.co/vocabulary/Vehicle", "doc_count": 39, "doc_count_error_upper_bound": 1, "height_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "mass_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "length_max": { "value": 210.0 }, "diameter_max": { "value": null } }, { "key": "https://swapi.co/vocabulary/Species", "doc_count": 38, "doc_count_error_upper_bound": 1, "height_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "mass_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "length_max": { "value": null }, "diameter_max": { "value": null } }, { "key": "https://swapi.co/vocabulary/Starship", "doc_count": 37, "doc_count_error_upper_bound": 1, "height_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "mass_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "length_max": { "value": 120000.0 }, "diameter_max": { "value": null } }, { "key": "https://swapi.co/vocabulary/FilmRelease", "doc_count": 29, "doc_count_error_upper_bound": 1, "height_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "mass_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "length_max": { "value": null }, "diameter_max": { "value": null } }, { "key": "https://swapi.co/vocabulary/Artificial", "doc_count": 12, "doc_count_error_upper_bound": 0, "height_stats": { "count": 10, "min": 96.0, "max": 200.0, "avg": 131.2, "sum": 1312.0 }, "mass_stats": { "count": 8, "min": 32.0, "max": 140.0, "avg": 69.75, "sum": 558.0 }, "length_max": { "value": null }, "diameter_max": { "value": null } }, { "key": "https://swapi.co/vocabulary/Droid", "doc_count": 12, "doc_count_error_upper_bound": 0, "height_stats": { "count": 10, "min": 96.0, "max": 200.0, "avg": 131.2, "sum": 1312.0 }, "mass_stats": { "count": 8, "min": 32.0, "max": 140.0, "avg": 69.75, "sum": 558.0 }, "length_max": { "value": null }, "diameter_max": { "value": null } }, { "key": "https://swapi.co/vocabulary/Amphibian", "doc_count": 11, "doc_count_error_upper_bound": 0, "height_stats": { "count": 11, "min": 180.0, "max": 229.0, "avg": 202.9090909090909, "sum": 2232.0 }, "mass_stats": { "count": 7, "min": 66.0, "max": 102.0, "avg": 87.14285714285714, "sum": 610.0 }, "length_max": { "value": null }, "diameter_max": { "value": null } }, { "key": "https://swapi.co/vocabulary/Film", "doc_count": 7, "doc_count_error_upper_bound": 1, "height_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "mass_stats": { "count": 0, "min": null, "max": null, "avg": null, "sum": 0.0 }, "length_max": { "value": null }, "diameter_max": { "value": null } }, { "key": "https://swapi.co/vocabulary/Unknown", "doc_count": 6, "doc_count_error_upper_bound": 0, "height_stats": { "count": 6, "min": 94.0, "max": 191.0, "avg": 157.66666666666666, "sum": 946.0 }, "mass_stats": { "count": 4, "min": 45.0, "max": 90.0, "avg": 70.0, "sum": 280.0 }, "length_max": { "value": null }, "diameter_max": { "value": null } }, { "key": "https://swapi.co/vocabulary/Wookiee", "doc_count": 4, "doc_count_error_upper_bound": 0, "height_stats": { "count": 4, "min": 228.0, "max": 234.0, "avg": 231.0, "sum": 924.0 }, "mass_stats": { "count": 4, "min": 112.0, "max": 136.0, "avg": 124.0, "sum": 496.0 }, "length_max": { "value": null }, "diameter_max": { "value": null } } ] } } } } }

Sub-aggregations

Bucket aggregations support bucket or metric sub-aggregations. For example, a terms aggregation with an avg sub-aggregation calculates an average value for each bucket of documents. There is no level or depth limit for nesting sub-aggregations.

This query uses metrics aggregations in sub-aggregation: create buckets by Planet id; calculate min, max, average, percentiles for resident.height for each planet.

Loading...
true
{ planet_search ( aggs: [ { name: "planet" value: { terms:{ field: "id" size: 10 } aggs:{ name: "residents" value: { nested: { path: "resident" } aggs:[ { name: "residentAvgHeight" value: { avg: { field: "resident.height" } } } { name: "residentMinHeight" value: { min: { field: "resident.height" } } } { name: "residentMaxHeight" value: { max: { field: "resident.height" } } } { name: "residentPercentilesHeight" value: { percentiles: { field: "resident.height" } } } ] } } } } ] ) { aggregations } }
{ "data": { "planet_search": { "aggregations": { "planet": { "doc_count_error_upper_bound": -1, "sum_other_doc_count": 51, "buckets": [ { "key": "https://swapi.co/resource/planet/8", "doc_count": 1, "residents": { "doc_count": 11, "residentPercentilesHeight": { "values": { "1.0": 96.0, "5.0": 99.05, "25.0": 165.0, "50.0": 183.0, "75.0": 193.25, "95.0": 223.1, "99.0": 224.0 } }, "residentMaxHeight": { "value": 224.0 }, "residentAvgHeight": { "value": 175.45454545454547 }, "residentMinHeight": { "value": 96.0 } } }, { "key": "https://swapi.co/resource/planet/1", "doc_count": 1, "residents": { "doc_count": 10, "residentPercentilesHeight": { "values": { "1.0": 97.00000000000001, "5.0": 97.0, "25.0": 165.0, "50.0": 175.0, "75.0": 183.0, "95.0": 202.0, "99.0": 202.0 } }, "residentMaxHeight": { "value": 202.0 }, "residentAvgHeight": { "value": 169.8 }, "residentMinHeight": { "value": 97.0 } } }, { "key": "https://swapi.co/resource/planet/28", "doc_count": 1, "residents": { "doc_count": 10, "residentPercentilesHeight": { "values": { "1.0": 66.0, "5.0": 66.0, "25.0": 81.0, "50.0": 144.5, "75.0": 196.5, "95.0": 200.0, "99.0": 200.0 } }, "residentMaxHeight": { "value": 200.0 }, "residentAvgHeight": { "value": 138.75 }, "residentMinHeight": { "value": 66.0 } } }, { "key": "https://swapi.co/resource/planet/10", "doc_count": 1, "residents": { "doc_count": 3, "residentPercentilesHeight": { "values": { "1.0": 182.99999999999997, "5.0": 183.0, "25.0": 190.5, "50.0": 213.0, "75.0": 225.0, "95.0": 229.0, "99.0": 229.0 } }, "residentMaxHeight": { "value": 229.0 }, "residentAvgHeight": { "value": 208.33333333333334 }, "residentMinHeight": { "value": 183.0 } } }, { "key": "https://swapi.co/resource/planet/2", "doc_count": 1, "residents": { "doc_count": 3, "residentPercentilesHeight": { "values": { "1.0": 150.0, "5.0": 150.0, "25.0": 159.5, "50.0": 188.0, "75.0": 190.25, "95.0": 191.0, "99.0": 191.0 } }, "residentMaxHeight": { "value": 191.0 }, "residentAvgHeight": { "value": 176.33333333333334 }, "residentMinHeight": { "value": 150.0 } } }, { "key": "https://swapi.co/resource/planet/9", "doc_count": 1, "residents": { "doc_count": 3, "residentPercentilesHeight": { "values": { "1.0": 167.0, "5.0": 167.0, "25.0": 167.75, "50.0": 170.0, "75.0": 180.5, "95.0": 184.0, "99.0": 184.0 } }, "residentMaxHeight": { "value": 184.0 }, "residentAvgHeight": { "value": 173.66666666666666 }, "residentMinHeight": { "value": 167.0 } } }, { "key": "https://swapi.co/resource/planet/14", "doc_count": 1, "residents": { "doc_count": 2, "residentPercentilesHeight": { "values": { "1.0": 228.0, "5.0": 228.0, "25.0": 228.0, "50.0": 231.0, "75.0": 234.0, "95.0": 234.0, "99.0": 234.0 } }, "residentMaxHeight": { "value": 234.0 }, "residentAvgHeight": { "value": 231.0 }, "residentMinHeight": { "value": 228.0 } } }, { "key": "https://swapi.co/resource/planet/22", "doc_count": 1, "residents": { "doc_count": 2, "residentPercentilesHeight": { "values": { "1.0": 170.0, "5.0": 170.0, "25.0": 170.0, "50.0": 175.0, "75.0": 180.0, "95.0": 180.0, "99.0": 180.0 } }, "residentMaxHeight": { "value": 180.0 }, "residentAvgHeight": { "value": 175.0 }, "residentMinHeight": { "value": 170.0 } } }, { "key": "https://swapi.co/resource/planet/37", "doc_count": 1, "residents": { "doc_count": 2, "residentPercentilesHeight": { "values": { "1.0": 178.0, "5.0": 178.0, "25.0": 178.0, "50.0": 179.0, "75.0": 180.0, "95.0": 180.0, "99.0": 180.0 } }, "residentMaxHeight": { "value": 180.0 }, "residentAvgHeight": { "value": 179.0 }, "residentMinHeight": { "value": 178.0 } } }, { "key": "https://swapi.co/resource/planet/51", "doc_count": 1, "residents": { "doc_count": 2, "residentPercentilesHeight": { "values": { "1.0": 166.0, "5.0": 166.0, "25.0": 166.0, "50.0": 168.0, "75.0": 170.0, "95.0": 170.0, "99.0": 170.0 } }, "residentMaxHeight": { "value": 170.0 }, "residentAvgHeight": { "value": 168.0 }, "residentMinHeight": { "value": 166.0 } } } ] } } } } }

This query shows sub-aggregations for character terms-film/terms-gender.

Loading...
true
{ character_search ( aggs: { name: "film" value: { nested: { path: "film" } aggs: { name: "film_terms" value: { terms: { field: "film.id" } aggs: { name: "reverse_nested" value: { reverse_nested: {} aggs: { name: "gender" value: { terms: { field: "gender" missing: "probably_droid" } } } } } } } } } ) { aggregations } }
{ "data": { "character_search": { "aggregations": { "film": { "doc_count": 173, "film_terms": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "https://swapi.co/resource/film/5", "doc_count": 40, "reverse_nested": { "doc_count": 40, "gender": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "male", "doc_count": 24 }, { "key": "female", "doc_count": 14 }, { "key": "probably_droid", "doc_count": 2 } ] } } }, { "key": "https://swapi.co/resource/film/4", "doc_count": 34, "reverse_nested": { "doc_count": 34, "gender": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "male", "doc_count": 27 }, { "key": "female", "doc_count": 4 }, { "key": "probably_droid", "doc_count": 2 }, { "key": "hermaphrodite", "doc_count": 1 } ] } } }, { "key": "https://swapi.co/resource/film/6", "doc_count": 34, "reverse_nested": { "doc_count": 34, "gender": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "male", "doc_count": 23 }, { "key": "female", "doc_count": 9 }, { "key": "probably_droid", "doc_count": 2 } ] } } }, { "key": "https://swapi.co/resource/film/3", "doc_count": 20, "reverse_nested": { "doc_count": 20, "gender": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "male", "doc_count": 15 }, { "key": "female", "doc_count": 2 }, { "key": "probably_droid", "doc_count": 2 }, { "key": "hermaphrodite", "doc_count": 1 } ] } } }, { "key": "https://swapi.co/resource/film/1", "doc_count": 18, "reverse_nested": { "doc_count": 18, "gender": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "male", "doc_count": 12 }, { "key": "probably_droid", "doc_count": 3 }, { "key": "female", "doc_count": 2 }, { "key": "hermaphrodite", "doc_count": 1 } ] } } }, { "key": "https://swapi.co/resource/film/2", "doc_count": 16, "reverse_nested": { "doc_count": 16, "gender": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "male", "doc_count": 12 }, { "key": "probably_droid", "doc_count": 3 }, { "key": "female", "doc_count": 1 } ] } } }, { "key": "https://swapi.co/resource/film/7", "doc_count": 11, "reverse_nested": { "doc_count": 11, "gender": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "male", "doc_count": 6 }, { "key": "female", "doc_count": 3 }, { "key": "probably_droid", "doc_count": 2 } ] } } } ] } } } } } }

The following GraphQL query shows how to aggregate the height field with different aggregation types: the count of the different heights, the min value of all heights, and the max value:

Loading...
true
query character_aggregations { character_search( aggs: [{ name: "heights", value: { terms: { field: "height" } } }, { name: "max-height", value: { max: { field: "height" } } }, { name:"min-height", value: { min: { field: "height" } } }] ) { max_score aggregations } }
{ "data": { "character_search": { "max_score": 1, "aggregations": { "max-height": { "value": 264 }, "heights": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 41, "buckets": [ { "key": 183, "doc_count": 7 }, { "key": 180, "doc_count": 5 }, { "key": 188, "doc_count": 5 }, { "key": 170, "doc_count": 4 }, { "key": 178, "doc_count": 4 }, { "key": 165, "doc_count": 3 }, { "key": 175, "doc_count": 3 }, { "key": 191, "doc_count": 3 }, { "key": 193, "doc_count": 3 }, { "key": 196, "doc_count": 3 } ] }, "min-height": { "value": 66 } } } } }

You can explore the GraphQL schema to see all available query and aggregation input types. This can be done with any GraphQL introspection tool, for example GraphiQL or GraphQL Playground.

You can also mix together queries, sorting, and aggregations as long as they are valid according to the Elasticsearch DSL.

Loading...
true
query character_aggregations { character_search( query: { match: { eyeColor: { query: "blue" } } } from: 5 size: 5 sort: { height: { order: desc } } aggs: [{ name: "heights", value: { terms: { field: "height" } } }, { name: "max-height", value: { max: { field: "height" } } }, { name:"min-height", value: { min: { field: "height" } } }] ) { max_score hits { score character { id name } } aggregations } }
{ "data": { "character_search": { "max_score": 1.435887, "hits": [ { "score": 1.435887, "character": { "id": "https://swapi.co/resource/tholothian/55", "name": "Adi Gallia" } }, { "score": 1.435887, "character": { "id": "https://swapi.co/resource/human/39", "name": "Ric Olié" } }, { "score": 1.435887, "character": { "id": "https://swapi.co/resource/human/62", "name": "Cliegg Lars" } }, { "score": 1.435887, "character": { "id": "https://swapi.co/resource/human/12", "name": "Wilhuff Tarkin" } }, { "score": 1.435887, "character": { "id": "https://swapi.co/resource/human/19", "name": "Jek Tono Porkins" } } ], "aggregations": { "max-height": { "value": 234 }, "heights": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 7, "buckets": [ { "key": 170, "doc_count": 2 }, { "key": 180, "doc_count": 2 }, { "key": 183, "doc_count": 2 }, { "key": 96, "doc_count": 1 }, { "key": 150, "doc_count": 1 }, { "key": 165, "doc_count": 1 }, { "key": 166, "doc_count": 1 }, { "key": 167, "doc_count": 1 }, { "key": 172, "doc_count": 1 }, { "key": 175, "doc_count": 1 } ] }, "min-height": { "value": 96 } } } } }