A solution that may be incomplete but helps a lot is the user filter_path . For example, suppose we have the following content in an index:
PUT foods/_doc/_bulk { "index" : { "_id" : "1" } } { "name" : "chocolate cake", "calories": "too much" } { "index" : { "_id" : "2" } } { "name" : "lemon pie", "calories": "a lot!" } { "index" : { "_id" : "3" } } { "name" : "pizza", "calories": "oh boy..." }
Such a search ...
GET foods/_search { "query": { "match_all": {} } }
... will give a lot of metadata:
{ "took" : 1, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : 3, "max_score" : 1.0, "hits" : [ { "_index" : "foods", "_type" : "_doc", "_id" : "2", "_score" : 1.0, "_source" : { "name" : "lemon pie", "calories" : "a lot!" } }, { "_index" : "foods", "_type" : "_doc", "_id" : "1", "_score" : 1.0, "_source" : { "name" : "chocolate cake", "calories" : "too much" } }, { "_index" : "foods", "_type" : "_doc", "_id" : "3", "_score" : 1.0, "_source" : { "name" : "pizza", "calories" : "oh boy..." } } ] } }
But if we give the search URL the filter_path=hits.hits._score ...
GET foods/_search?filter_path=hits.hits._source { "query": { "match_all": {} } }
... it will return only the source (although still deeply nested):
{ "hits" : { "hits" : [ { "_source" : { "name" : "lemon pie", "calories" : "a lot!" } }, { "_source" : { "name" : "chocolate cake", "calories" : "too much" } }, { "_source" : { "name" : "pizza", "calories" : "oh boy..." } } ] } }
You can even filter the fields:
GET foods/_search?filter_path=hits.hits._source { "query": { "match_all": {} } }
... and you will get this:
{ "hits" : { "hits" : [ { "_source" : { "name" : "lemon pie" } }, { "_source" : { "name" : "chocolate cake" } }, { "_source" : { "name" : "pizza" } } ] } }
And you can do much more if you want, just look at the documentation .