I would like to build an ecommerce search engine for different kind of products with elasticsearch 2.4.2 and a spring boot 1.5.4 microservice which provides a search api. I created a working mapping with different analyzers and got it also working with a native elasticsearch json query using sense. You can see the working query (native) at the bottom of this question. This query returns a list of search results with some aggregations for the facet navigation. So it's working fine. Using spring boot with spring-data-elasticsearch to execute this query results in some exception while serializing the AggregatedPage result to json. You can find the exception in the following code-quotes. Does somebody know what's wrong here? Is there a mistake building the query in spring boot or is it a framework bug? Does somebody know a workaround or solution for that?
The controller method:
@RequestMapping(value = "/products", method = RequestMethod.GET)
@ResponseStatus(HttpStatus.OK)
public AggregatedPage<PageDocument> searchProducts(@RequestParam("q") String searchPhrase, Pageable pageable) {
return searchService.search(searchPhrase, pageable);
}
Request response (exception):
{
"timestamp": 1499961386848,
"status": 500,
"error": "Internal Server Error",
"exception": "org.springframework.http.converter.HttpMessageNotWritableException",
"message": "Could not write JSON: show_terms_doc_count_error is false; nested exception is com.fasterxml.jackson.databind.JsonMappingException: show_terms_doc_count_error is false (through reference chain: org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl[\"aggregations\"]->org.elasticsearch.search.aggregations.InternalAggregations[\"asMap\"]->com.google.common.collect.Maps$TransformedEntriesMap[\"stringFacetList\"]->org.elasticsearch.search.aggregations.bucket.nested.InternalNested[\"aggregations\"]->org.elasticsearch.search.aggregations.InternalAggregations[\"asMap\"]->com.google.common.collect.Maps$TransformedEntriesMap[\"stringFacetNames\"]->org.elasticsearch.search.aggregations.bucket.terms.StringTerms[\"buckets\"]->java.util.ArrayList[0]->org.elasticsearch.search.aggregations.bucket.terms.StringTerms$Bucket[\"docCountError\"])",
"path": "/search/products/"
}
The searchService search method:
public AggregatedPage<PageDocument> search(String searchPhrase, Pageable pageable) {
NestedBuilder stringAggregationBuilder = AggregationBuilders.nested("stringFacetList")
.path("searchData.stringFacet")
.subAggregation(
terms("stringFacetNames")
.field("searchData.stringFacet.facetName")
.subAggregation(
terms("attributeValue")
)
.subAggregation(
terms("stringFacetValues")
.field("searchData.stringFacet.facetValue")
));
NestedQueryBuilder searchQuery = nestedQuery("searchData", multiMatchQuery(searchPhrase)
.field("searchData.fullText", 2)
.field("searchData.fullTextBoosted", 7)
.fuzziness(Fuzziness.TWO)
.analyzer("full_text_search_analyzer")
.type(Type.MOST_FIELDS));
SearchQuery nativeSearchQueryBuilder = new NativeSearchQueryBuilder()
.withPageable(pageable)
.withQuery(searchQuery)
.addAggregation(stringAggregationBuilder)
.build();
return pageDocumentRepository.search(nativeSearchQueryBuilder);
}
The working ES-Query (native):
POST /page-documents/page-document/_search
{
"query": {
"nested": {
"query": {
"multi_match": {
"query": "Samsung",
"fields": [
"searchData.fullText^2.0",
"searchData.fullTextBoosted^7.0"
],
"type": "most_fields",
"analyzer": "full_text_search_analyzer",
"fuzziness": "2"
}
},
"path": "searchData"
}
},
"aggregations": {
"agg_string_facet": {
"nested": {
"path": "searchData.stringFacet"
},
"aggregations": {
"facet_name": {
"terms": {
"field": "searchData.stringFacet.facetName"
},
"aggregations": {
"facet_value": {
"terms": {
"field": "searchData.stringFacet.facetValue"
}
}
}
}
}
}
}
}
How a native search result using the query above looks like (executed with sense):
{
"took": 20,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 33,
"max_score": 3.7071486,
"hits": [
{
"_index": "page-documents",
"_type": "page-document",
"_id": "77891",
"_score": 3.7071486,
"_source": {
"id": "77891",
"lastUpdated": "2017-07-13T13:08:56.231+0000",
"documentType": "PRODUCT",
"searchResultData": {
"id": "77891",
"name": "Samsung ProXpress M3825DW Drucker",
"ean": "8806085488533",
"url": null,
"manufacturerName": "Samsung",
"description": "Samsung ProXpress M3825DW - Drucker - monochrom - Duplex - Laser - A4/Legal - 1200 x 1200 dpi - bis zu 38 Seiten/Min. - Kapazität: 300 Blätter - USB 2.0, LAN, Wi-Fi(n)"
},
"searchData": {
"fullText": "8806085488533 77891 Samsung ProXpress M3825DW Drucker Samsung",
"fullTextBoosted": "Samsung ProXpress M3825DW Drucker",
"stringFacet": [
{
"facetName": "manufacturer",
"facetValue": "Samsung"
}
],
"numberFacet": null
},
"completionTerms": null,
"suggestionTerms": null,
"scores": {
"amazonSalesRank": 0.27778,
"contentQuality": 0.15,
"isDeal": 0
},
"stringSort": {
"name": "Samsung ProXpress M3825DW Drucker"
},
"numberSort": {
"id": 77891
}
}
}
]
},
"aggregations": {
"agg_string_facet": {
"doc_count": 57,
"facet_name": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "manufacturer",
"doc_count": 28,
"facet_value": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "Samsung",
"doc_count": 15
}
]
}
},
{
"key": "color",
"doc_count": 19,
"facet_value": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "Schwarz",
"doc_count": 12
}
]
}
},
{
"key": "productType",
"doc_count": 10,
"facet_value": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "LCD-Flachdisplay mit LED-Hintergrundbeleuchtung",
"doc_count": 2
}
]
}
}
]
}
}
}
}