首页 > 解决方案 > Spring Data Elasticsearch 是否支持 Multi Search API?

问题描述

我正在使用 Spring Data Elasticsearch,并且有兴趣利用 Elasticsearch 6.2 的 Multi Search API 在单个 API 请求中执行多个搜索。

https://www.elastic.co/guide/en/elasticsearch/reference/6.2/search-multi-search.html

目前使用 Spring Data ElasticsearchNativeSearchQueryBuilder构建搜索查询,并ElasticsearchTemplate执行搜索请求。在查看 Spring Data 代码和浏览文档后,我还没有找到任何这些方法公开的用于构造或提交 Multi Search 请求的方法。

Spring Data Elasticsearch 是否通过他们ElasticsearchTemplate或我可能不知道的其他一些客户端/机制支持 Multi Search API?

Elasticsearch 在他们的 Java API 中提供了这个功能,所以我追求的是类似于下面的东西,但不幸的是我必须使用 Spring Data Elasticsearch。

https://www.elastic.co/guide/en/elasticsearch/client/java-api/6.2/java-search-msearch.html

标签: javaspringelasticsearchspring-dataspring-data-elasticsearch

解决方案


不,Spring Data Elasticsearch 暂时不支持多搜索。我也遇到了同样的问题,我正在做一个 PR来添加这个功能。现在,我想出了以下解决方法:

@Override
public YYY findBy(XXX xxx) {
  Client client = template.getClient();
  MultiSearchRequest request = new MultiSearchRequest();
  // build searchQuery like normal
  for (NativeSearchQuery searchQuery : queries) {
    request.add(prepareSearch(client, searchQuery));
  }
  ActionFuture<MultiSearchResponse> future = client
      .multiSearch(request);
  MultiSearchResponse response = future.actionGet();
  Item[] items = response.getResponses();
  for (int i = 0; i < items.length; i++) {
    AggregatedPage<XXX> ts = resultMapper.mapResults(items[i].getResponse(), XXX.class, page);
    // do with page
  }
}

private SearchRequestBuilder prepareSearch(Client client, SearchQuery searchQuery) {
  Assert.notNull(searchQuery.getIndices(), "No index defined for Query");
  Assert.notNull(searchQuery.getTypes(), "No type defined for Query");

  int startRecord = 0;
  SearchRequestBuilder searchRequest = client.prepareSearch(toArray(searchQuery.getIndices()))
      .setSearchType(searchQuery.getSearchType()).setTypes(toArray(searchQuery.getTypes()));

  if (searchQuery.getSourceFilter() != null) {
    SourceFilter sourceFilter = searchQuery.getSourceFilter();
    searchRequest.setFetchSource(sourceFilter.getIncludes(), sourceFilter.getExcludes());
  }

  if (searchQuery.getPageable().isPaged()) {
    startRecord = searchQuery.getPageable().getPageNumber() * searchQuery.getPageable().getPageSize();
    searchRequest.setSize(searchQuery.getPageable().getPageSize());
  }
  searchRequest.setFrom(startRecord);

  if (!searchQuery.getFields().isEmpty()) {
    searchRequest.setFetchSource(toArray(searchQuery.getFields()), null);
  }

  if (searchQuery.getSort() != null) {
    for (Sort.Order order : searchQuery.getSort()) {
      searchRequest.addSort(order.getProperty(),
          order.getDirection() == Sort.Direction.DESC ? SortOrder.DESC : SortOrder.ASC);
    }
  }

  if (searchQuery.getMinScore() > 0) {
    searchRequest.setMinScore(searchQuery.getMinScore());
  }

  if (searchQuery.getFilter() != null) {
    searchRequest.setPostFilter(searchQuery.getFilter());
  }

  if (!isEmpty(searchQuery.getElasticsearchSorts())) {
    for (SortBuilder sort : searchQuery.getElasticsearchSorts()) {
      searchRequest.addSort(sort);
    }
  }

  if (!searchQuery.getScriptFields().isEmpty()) {
    //_source should be return all the time
    //searchRequest.addStoredField("_source");
    for (ScriptField scriptedField : searchQuery.getScriptFields()) {
      searchRequest.addScriptField(scriptedField.fieldName(), scriptedField.script());
    }
  }

  if (searchQuery.getHighlightFields() != null) {
    for (HighlightBuilder.Field highlightField : searchQuery.getHighlightFields()) {
      searchRequest.highlighter(new HighlightBuilder().field(highlightField));
    }
  }

  if (!isEmpty(searchQuery.getIndicesBoost())) {
    for (IndexBoost indexBoost : searchQuery.getIndicesBoost()) {
      searchRequest.addIndexBoost(indexBoost.getIndexName(), indexBoost.getBoost());
    }
  }

  if (!isEmpty(searchQuery.getAggregations())) {
    for (AbstractAggregationBuilder aggregationBuilder : searchQuery.getAggregations()) {
      searchRequest.addAggregation(aggregationBuilder);
    }
  }

  if (!isEmpty(searchQuery.getFacets())) {
    for (FacetRequest aggregatedFacet : searchQuery.getFacets()) {
      searchRequest.addAggregation(aggregatedFacet.getFacet());
    }
  }

  return searchRequest.setQuery(searchQuery.getQuery());
}

推荐阅读