Elasticsearch json response to SearchResponse object

Hi There,

Could someone help to get it working?
So far I got the solution below. This works for simple queries, however it doesn't work for aggregations and I am getting exception ParsingException "Could not parse aggregation keyed as [dashboard]"

JsonXContentParser xContentParser = new JsonXContentParser(NamedXContentRegistry.EMPTY,
new JsonFactory().createParser(SearchResponse response = SearchResponse.fromXContent(xContentParser);

The response I need to parse is provided below:
{
"took": 16,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 1,
"hits": [
{
"_index": "demo",
"_type": "demo",
"_id": "OSScKmIBKBDaRuGPyr42",
"_score": 1,
"_source": {
"demoId": "2",
"demoName": "j",
"uniqueDemo": "jab1980xy11b"
}
},
{
"_index": "demo",
"_type": "demo",
"_id": "OCScKmIBKBDaRuGPyr42",
"_score": 1,
"_source": {
"demoId": "2",
"demoName": "j",
"uniqueDemo": "jmb1970oi611234554321123a"
}
}
]
},
"aggregations": {
"dashboard": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "jab1980xy11b",
"doc_count": 1,
"data": {
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "demo",
"_type": "demo",
"_id": "OSScKmIBKBDaRuGPyr42",
"_score": 1,
"_source": {
"demoId": "2",
"demoName": "j"
}
}
]
}
}
},
{
"key": "jmb1970oi611234554321123a",
"doc_count": 1,
"data": {
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "demo",
"_type": "demo",
"_id": "OCScKmIBKBDaRuGPyr42",
"_score": 1,
"_source": {
"demoId": "2",
"demoName": "j"
}
}
]
}
}
}
]
}
}
}

1 Like

Out of curiosity why you are not calling the search(SearchRequest) method? It gives you back a SearchResponse object (including aggs)

We do so in our application. However, I am writing junit test and want to verify that the business logic is correct, hence I want to interrogate the SearchResponse object.
If there is better way to write unit test I would be more then happy to hear.

As far as I can read the code

It looks like innerFromXContent is also parsing the aggs part.

This is calling:

Behind the scene this needs to know what kind of aggregation you asked for, what is the java type to use. The magic is happening here:

So you need to add a prefix like terms# if you are getting back a terms aggregation.

terms#foo as the javadoc example says.

I hope this can help.

1 Like

Thank you for your help. Behind the scene magic explanation helped me to get working solution.

Will post it after a little bit more testing.

1 Like

Working solution for someone that might have the same issue.

Elasticsearch response with aggregation example:

Helper method to create NamedXContentRegistry

public static List<NamedXContentRegistry.Entry> getDefaultNamedXContents() {
    Map<String, ContextParser<Object, ? extends Aggregation>> map = new HashMap<>();
    map.put(TopHitsAggregationBuilder.NAME, (p, c) -> ParsedTopHits.fromXContent(p, (String) c));
    map.put(StringTerms.NAME, (p, c) -> ParsedStringTerms.fromXContent(p, (String) c));
    List<NamedXContentRegistry.Entry> entries = map.entrySet().stream()
            .map(entry -> new NamedXContentRegistry.Entry(Aggregation.class, new ParseField(entry.getKey()), entry.getValue()))
            .collect(Collectors.toList());
  return entries;
}

Method to get SearchResponse from String/Json

public static SearchResponse getSearchResponseFromJson(String jsonResponse){
    try {
        NamedXContentRegistry registry = new NamedXContentRegistry(DashboardCuke.getDefaultNamedXContents());
        XContentParser parser = JsonXContent.jsonXContent.createParser(registry, jsonResponse);
        return SearchResponse.fromXContent(parser);
    } catch (IOException e) {
        System.out.println("exception " + e);
    }catch (Exception e){
        System.out.println("exception " + e);
    }
    return new SearchResponse();
}
1 Like

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.