1

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();

}
1
  • You should have a look at Jest Commented Mar 16, 2016 at 10:20

0

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.