1

I'm trying to query pricing stats on products I am recording in my Elasticsearch Database by product number. The pricing may be for new, used or refurbished products, so I wish to filter on condition. The condition filter works as a JSON query in Marvel returning stats based on two price documents with condition new.

When I try to do similar using the Java API, I am getting stats based on 4 documents that includes 2 new and 2 refurbished.

Could anyone please identify what I am doing wrong in the Java code below?

Thanks.

Here's the working JSON Query:

GET /stats/price/_search
{
  "query": {
  "match_phrase": {"mpc": "MGTX2LL/A"}
  },
  "size": 0,
  "aggs" : {
      "low_price_stats" : { 
      "filter": {
          "term" : { "condition" : "new"}
      },
      "aggs" : {
          "price_stats" : { "extended_stats" : { "field" : "price" } }
      }
    }
  }
}

And the problematic Java:

public Aggregations aggByManufacturerPartNumber(String mpn) {

    SearchQuery searchQuery = new NativeSearchQueryBuilder()
        .withIndices("stats")
        .withTypes("price")
        .withQuery(termQuery("mpn", mpn))
        .withFilter(
            FilterBuilders.termFilter("condition", "New")
        )
        .addAggregation(AggregationBuilders.extendedStats("stats_agg").field("price"))
        .build();

    Aggregations aggregations = elasticsearchTemplate.query(searchQuery, new ResultsExtractor<Aggregations>() {
        @Override
        public Aggregations extract(SearchResponse response) {
            return response.getAggregations();
        }
    });

    return aggregations;
}

1 Answer 1

1

In your Java code you're only building the price_stats sub-aggregation without its parent filter aggregation. The call to withFilter will create a filter at the query level, not at the aggregation level. The correct Java code that matches your JSON query would be like this:

// build top-level filter aggregation
FilterAggregationBuilder lowPriceStatsAgg = AggregationBuilders.filter("low_price_stats")
    .filter(FilterBuilders.termFilter("condition", "new"));

// build extended stats sub-aggregation
lowPriceStatsAgg.subAggregation(AggregationBuilders.extendedStats("stats_agg").field("price"));

// build query
SearchQuery searchQuery = new NativeSearchQueryBuilder()
    .withIndices("stats")
    .withTypes("price")
    .withQuery(termQuery("mpn", mpn))
    .addAggregation(lowPriceStatsAgg)
    .build();

// then get the results
Aggregations aggs = response.getAggregations();
Filter lowPriceStats = aggs.get("low_price_stats");
ExtendedStats statsAgg = lowPriceStats.get("stats_agg");

Besides, also note that in your JSON query you have a match_phrase on the mpc field while in your Java code you have a term query on the mpn field. So you probably need to fix that, too, but the above code fixes the aggregation part only.

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

1 Comment

OK, Thanks! I'm almost there. The sub aggregation appears to be lowPriceStatsAgg.subAggregation(...). I'm getting a null after the query and extractor. Because it's a subAggregation, do I need to make a different ResultExtractor?

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.