1

Je voudrais construire un moteur de recherche e-commerce pour différents types de produits avec elasticsearch 2.4.2 et un microservice de démarrage 1.5.4 qui fournit une API de recherche. J'ai créé une cartographie de travail avec différents analyseurs et je l'ai aussi travaillé avec une requête JSS élastique elasticsearch en utilisant le sens. Vous pouvez voir la requête de travail (natif) au bas de cette question. Cette requête renvoie une liste de résultats de recherche avec des agrégations pour la navigation par facette. Donc ça fonctionne bien. L'utilisation de spring boot avec spring-data-elasticsearch pour exécuter cette requête entraîne une exception lors de la sérialisation du résultat AggregatedPage en json. Vous pouvez trouver l'exception dans les citations de code suivantes. Est-ce que quelqu'un sait ce qui ne va pas ici? Y at-il une erreur de construction de la requête au démarrage du printemps ou est-ce un bug de l'infrastructure? Est-ce que quelqu'un sait une solution de contournement ou une solution pour cela?Quelle est la bonne façon de sérialiser les résultats de recherche elasticsearch avec des agrégations à json en utilisant spring boot?

La méthode du contrôleur:

@RequestMapping(value = "/products", method = RequestMethod.GET) 
    @ResponseStatus(HttpStatus.OK) 
    public AggregatedPage<PageDocument> searchProducts(@RequestParam("q") String searchPhrase, Pageable pageable) { 
     return searchService.search(searchPhrase, pageable); 
    } 

réponse à la demande (d'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/" 
} 

La méthode de recherche SearchService:

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

Le travail ES-Query (natif):

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" 
        } 
        } 
       } 
      } 
     } 
     } 
    } 
} 

Comment un résultat de recherche natif à l'aide de la requête ci-dessus ressemble (exécuté avec le sens):

{ 
    "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 
         } 
        ] 
        } 
       } 
      ] 
     } 
     } 
    } 
} 

Répondre

0

Vous devez définir le paramètre show_term_doc_count_error true. Cela affichera une valeur d'erreur pour chaque terme renvoyé par l'agrégation. Voir Per bucket document count error.

Le org.elasticsearch.search.aggregations.bucket.terms.TermBuilder vous utilisez la méthode fournit showTermDocCountError (de showTermDocCountError booléen) qui peut être utilisé pour régler la show_term_doc_count_error true.