ElasticSearch Rest高级客户端重新映射错误

时间:2020-03-06 15:15:32

标签: java spring spring-boot elasticsearch elasticsearch-high-level-restclient

我正在尝试创建一个类,该类将通过具有操作(创建,createBatch,删除,removeBatch,更新,updateBatch)的Rest High Level Client自动写入ElasticSearch,并且所有这些操作均有效,并且我的测试用例均成功。为了增加灵活性,我想实现以下方法:(查找,findAll,getFirsts(n),getLasts(n))。 find(key)和findAll()都可以正常工作,但是getFirsts(n)和getLasts(n)根本不起作用。

这里是上下文: 在每个测试用例之前->确保索引“ test”存在,如果不存在则创建索引 在每个测试用例之后->删除索引“ test” 对于getFirsts(n)和getLasts(n),我称其为create在ElasticSearch中有一些项目,然后根据uniqueKey进行搜索。

这是我的测试对象的映射:

{
  "properties": {
    "date": { "type": "long" },
    "name": { "type": "text" },
    "age": { "type": "integer" },
    "uniqueKey": { "type": "keyword" }
  }
}

这是我的测试用例:

@Test
public void testGetFirstByIds() throws BeanPersistenceException {
    List<StringTestDataBean> beans = new ArrayList<>();
    StringTestDataBean bean1 = new StringTestDataBean();
    bean1.setName("Tester");
    bean1.setAge(22);
    bean1.setTimeStamp(23213987321712L);
    beans.add(elasticSearchService.create(bean1));

    StringTestDataBean bean2 = new StringTestDataBean();
    bean1.setName("Antonio");
    bean1.setAge(27);
    bean1.setTimeStamp(2332321117321712L);
    beans.add(elasticSearchService.create(bean2));

    Assert.assertNotNull("The beans created should not be null", beans);
    Assert.assertEquals("The uniqueKeys of the fetched list should match the existing",
            beans.stream()
                .map(ElasticSearchBean::getUniqueKey)
                .sorted((b1,b2) -> Long.compare(Long.parseLong(b2),Long.parseLong(b1)))
                .collect(Collectors.toList()),

            elasticSearchService.getFirstByIds(2).stream()
                .map(ElasticSearchBean::getUniqueKey)
                .collect(Collectors.toList())
    );
}

这是getFirstByIds(n):

@Override
public Collection<B> getFirstByIds(int entityCount) throws BeanPersistenceException {
    assertBinding();
    FilterContext filterContext = new FilterContext();
    filterContext.setLimit(entityCount);
    filterContext.setSort(Collections.singletonList(new FieldSort("uniqueKey",true)));
    return Optional.ofNullable(find(filterContext)).orElseThrow();
}

这是find(filterContext):

@Override
public List<B> find(FilterContext filter) throws BeanPersistenceException {
    assertBinding();
    BoolQueryBuilder query = QueryBuilders.boolQuery();
    List<FieldFilter> fields = filter.getFields();
    StreamUtil.ofNullable(fields)
            .forEach(fieldFilter -> executeFindSwitchCase(fieldFilter,query));

    SearchSourceBuilder builder = new SearchSourceBuilder().query(query);
    builder.from((int) filter.getFrom());
    builder.size(((int) filter.getLimit() == -1) ? FILTER_LIMIT : (int) filter.getLimit());

    SearchRequest request = new SearchRequest();
    request.indices(index);
    request.source(builder);
    List<FieldSort> sorts = filter.getSort();
    StreamUtil.ofNullable(sorts)
            .forEach(fieldSort -> builder.sort(SortBuilders.fieldSort(fieldSort.getField()).order(
                    fieldSort.isAscending() ? SortOrder.ASC : SortOrder.DESC)));

    try {
        if (strict)
            client.indices().refresh(new RefreshRequest(index), RequestOptions.DEFAULT);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        List<B> results = new ArrayList<>();

        for (SearchHit hit : hits)
            results.add(objectMapper.readValue(hit.getSourceAsString(), clazz));

        return results;
    }
    catch(IOException e){
        logger.error(e.getMessage(),e);
    }
    return null;
}

如果我多次运行测试用例,就会发生此问题。第一次,测试顺利通过,但是只要我们达到第二个测试,我都会遇到异常:

ElasticsearchStatusException[Elasticsearch exception [type=search_phase_execution_exception, reason=all shards failed]
]; nested: ElasticsearchException[Elasticsearch exception [type=illegal_argument_exception, reason=Fielddata is disabled on text fields by default. Set fielddata=true on [name] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead.]];

环顾了一整天后,我意识到该地图已从原始地图(开始时指定的地图)中更改,并使用以下内容自动创建:

"test": {
        "aliases": {},
        "mappings": {
            "properties": {
                "age": {
                    "type": "long"
                },
                "name": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "timeStamp": {
                    "type": "long"
                },
                "uniqueKey": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                }
            }
        }

如我所见,映射会自动更改并引发错误。 感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

只有在插入文档时字段的映射不存在时,Elastic才会创建动态映射。检查是否在将文档添加到索引之前进行放置映射调用。如果映射是静态应用的,请确保将文档插入正确的索引。