I am starting out on Elasticsearch. The scalability and performance is awesome, but I'm having trouble with the java API. Given some profile data where the id is a username and the profile contains attributes and scores (eg strength : 30, dexterity : 72, magic : 48) I want to get the top profiles for a particular combination of attributes eg strength + dexterity, or strength + magic etc.
Here is a query that I've used in Sense, which does exactly what I need:
GET_search{
"size": 0,
"aggs": {
"group by profile": {
"terms": {
"field": "profileId",
"order": {
"score_return": "desc"
}
},
"aggs": {
"score_return": {
"sum": {
"script": "doc['strength'].value + doc['dexterity'].value"
}
}
}
}
}
}
So now I want to port this query into my Java code. I managed to get it working, but it feels like it's extremely ugly - is there a better way of querying this data, or perhaps some library out there with a nice API, that can bind results to fields with annotations etc? Any suggestions welcome. This is what I have so far (it works, I just don't like the look of the code):
private void run() throws UnknownHostException {
InetAddress inetAddress = InetAddress.getByName(HOST_IP);
InetSocketTransportAddress transportAddress = new InetSocketTransportAddress(inetAddress, HOST_PORT);
Client client = TransportClient.builder().build().addTransportAddress(transportAddress);
String queryString = "{ \"aggs\": { \"group by profile\": { \"terms\": { \"field\": \"profileId\", \"order\": { \"score_return\": \"desc\" } }, \"aggs\": { \"score_return\": { \"sum\": { \"script\": \"doc['dexterity'].value + doc['strength'].value\" } } } } } }";
//Sample Query - JSONObject
//We convert the raw query string to JSONObject to avoid query parser error in Elasticsearch
JSONObject queryStringObject = new JSONObject(queryString);
//Elasticsearch Response
SearchResponse response = client.prepareSearch("profiles").setTypes("profile").setSource(queryStringObject.toString()).execute().actionGet();
//Elasticsearch Response Hits
SearchHits hits = response.getHits();
Aggregations aggregations = response.getAggregations();
Map<String, Aggregation> aggsMap = aggregations.asMap();
Aggregation groupBy = aggsMap.get("group by profile");
System.out.println(groupBy);
StringTerms st = ((StringTerms)groupBy);
System.out.println(st);
List<Bucket> buckets = st.getBuckets();
for(Bucket bucket : buckets) {
System.out.println(bucket.getKeyAsString());
Aggregation score = bucket.getAggregations().get("score_return");
String value = ((InternalSum)score).getValueAsString();
System.out.println(value);
}
client.close();
}