19

I am using the Java API for Elasticsearch. Having saved entities into indexes, it is possible to retrieve them together with the complete source. However, I only want to retrieve selected fields, and that is not working.

The folowing sample code:

SearchResponse response = client.prepareSearch("my-index")
   .setTypes("my-type")
   .setSearchType(SearchType.QUERY_AND_FETCH)
   .setFetchSource(true)
   .setQuery(QueryBuilders.termsQuery("field1", "1234"))
   .addFields("field1")
   .execute()
   .actionGet();

for (SearchHit hit : response.getHits()){
   Map<String, SearchHitField> fields = hit.getFields();
   System.out.println(fields.size());
   Map map = hit.getSource();
   map.toString();
}

will retrieve the correct entities from the index, including the complete source.

For example, this is a snippet of the response :

"hits" : {
  "total" : 1301,
  "max_score" : 0.99614644,
  "hits" : [ {
  "_index" : "my-index",
  "_type" : "my-type",
  "_id" : "AU2P68COpzIypBTd80np",
  "_score" : 0.99614644,
  "_source":{"field1":"1234", ...}]}
}, {

However, while response.getHits() returns the expected number of hits, the fields and source within each hit is empty.

I am expecting each hit to contain the field specified in the line:

.addFields("field1")

Commenting out the line

.setFetchSource(true)

will cause the response not to include the source at all.

The version of Elasticsearch is 1.5.0

The following is the maven dependency the Java API:

<dependency>
   <groupId>com.sksamuel.elastic4s</groupId>
   <artifactId>elastic4s_2.11</artifactId>
   <version>1.5.5</version>
</dependency>

Obiously, for performance reasons, I don't want to have to retrieve the complete entity. Does anyone know how to limit the retrieval to selected fields? Thanks

1 Answer 1

49

You can specify the fields you need using the setFetchSource(String[] includes, String[] excludes) method. Try this instead

SearchResponse response = client.prepareSearch("my-index")
   .setTypes("my-type")
   .setSearchType(SearchType.QUERY_AND_FETCH)
   .setFetchSource(new String[]{"field1"}, null)
   .setQuery(QueryBuilders.termsQuery("field1", "1234"))
   .execute()
   .actionGet();

for (SearchHit hit : response.getHits()){
   Map map = hit.getSource();
   map.toString();
}

map will only contain the fields you've specified.

Note that .setFetchSource("field1", null) (if you need a single field) or .setFetchSource("field*", null) (if you need several wildcarded fields) would work, too.

Sign up to request clarification or add additional context in comments.

6 Comments

@user1052610 were you able to use the suggested solution?
Didn't work for me with ElasticSearch 5.x. :( It returns an empty "_source" field in the response, and doesn't copy "field1" as a real field.
@cs94njw That's not supposed to have changed according to the source. Feel free to create a new question referencing this one, so we can sort it out.
Could one filter down to child properties of a json field value with this approach?
@Yoshimitsu yes definitely, like parent.child.grandchild
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.