SpringBoot 整合 ES 进行各种高级查询搜索

上一章:《ElasticSearch集群的搭建》


8.1 环境准备

如果你还未安装es的相关信息,请先移步至:《ElasticSearch安装》进行安装

如果您的SpringBoot项目还未整合es,请移步至:《SpringBoot整合ElasticSearch实现模糊查询,批量CRUD,排序,分页,高亮》

同时本文的操作中涉及到ElasticSearchRepository和ElasticsearchRestTemplate的使用,如果您还不是很理解他们是怎么使用的,请移步:《ElasticSearchRepository和ElasticsearchRestTemplate的使用》

如果以上内容您都有掌握或了解,那就继续向下学习吧

8.2 数据准备

因为本文都是数据的搜索,所以我们需要在我们的es服务器里先插入一些数据以供我们后面使用
esUserService


public interface EsUserService extends ElasticsearchRepository<User, Integer> {
    
    
}

@RestController
public class EsController {
    
    
    @Autowired
    private ElasticsearchRestTemplate elasticsearchTemplate;
    @Autowired
    private EsUserService esUserService;
    @Autowired
    private RestHighLevelClient client;

    private String[] names = {
    
    "诸葛亮", "曹操", "李白", "韩信", "赵云", "小乔", "狄仁杰", "李四", "诸小明", "王五"};
    private String[] infos = {
    
    "我来自中国的一个小乡村,地处湖南省", "我来自中国的一个大城市,名叫上海,人们称作魔都"
            , "我来自杭州,这是一个浪漫的城市"};

    /**
     * 准备数据
     *
     * @return
     */
    @GetMapping("prepareDate")
    public Object saveUser() {
    
    
        //添加索引mapping索引会自动创建但mapping自只用默认的这会导致分词器不生效 所以这里我们手动导入mapping
        Random random = new Random();
        List<User> users = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
    
    
            User user = new User();
            user.setId(i);
            user.setName(names[random.nextInt(9)]);
            user.setAge(random.nextInt(40) + i);
            user.setInfo(infos[random.nextInt(2)]);
            users.add(user);
        }
        Iterable<User> users1 = esUserService.saveAll(users);

        return users1;
    }
}

在这里插入图片描述

下面开始我们本文的重点
由于我们需要频繁的使用map转对象,所以给大家一个比较好用的map转对象方法

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.util.Map;
import java.util.Objects;

/**
 * 利用反射讲数据转化为Object
 *
 * @param <T>
 */
public class BeanHandler<T> {
    
    
    private Class<T> clazz;

    public BeanHandler(Class<T> clazz) {
    
    
        this.clazz = clazz;
    }

    /**
     * 讲sql 查询结果 ResultSet转化为对象
     *
     * @param rs
     * @return
     * @throws Exception
     */
    public T handle(ResultSet rs) throws Exception {
    
    
        //结果集默认指向为第一个数据的前一个
        if (rs.next()) {
    
    
            //根据传入的字节码创建传入的指定对象
            T obj = clazz.newInstance();
            //获取指定字节码信息
            BeanInfo beanInfo = Introspector.getBeanInfo(clazz, Object.class);
            //获取所有属性描述器
            PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor pd : pds) {
    
    
                //获取结果集中对应字段名的值
                Object o = rs.getObject(pd.getName());
                //执行当前方法并传入参数
                pd.getWriteMethod().invoke(obj, o);
            }
            return obj;
        }
        return null;
    }

    /**
     * 将map 利用反射转化为对象
     *
     * @param map
     * @return
     * @throws Exception
     */
    public T handle(Map<String, Object> map) throws Exception {
    
    
        //结果集默认指向为第一个数据的前一个
        //根据传入的字节码创建传入的指定对象
        T obj = clazz.newInstance();
        BeanInfo beanInfo = Introspector.getBeanInfo(clazz, Object.class);
        PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();

        for (PropertyDescriptor pd : pds) {
    
    
            Object o = map.get(pd.getName());
            if (Objects.nonNull(o)) {
    
    
                // !!!这里需要对属性类型做强制类型转化,
                o = getPropertyTypeObject(pd, o);
                // 下面的方法相当于属性的 set方法
                pd.getWriteMethod().invoke(obj, o);
            }
        }
        return obj;
    }


    /**
     * 将对应的mapValue 强转为实体类对应的类型
     *
     * @param pd
     * @param o
     * @return
     */
    public Object getPropertyTypeObject(PropertyDescriptor pd, Object o) {
    
    
        //当前属性的类型
        String name = pd.getPropertyType().getName();
        name = name.substring(name.lastIndexOf(".") + 1);
        switch (name) {
    
    
            case "String":
                o = String.valueOf(o);
                break;
            case "Long":
                o = Long.valueOf(String.valueOf(o));
                break;
            case "Double":
                o = Double.valueOf(String.valueOf(o));
                break;
            case "Integer":
                o = Integer.valueOf(String.valueOf(o));
                break;
            case "BigDecimal":
                o = new BigDecimal(String.valueOf(o));
                break;
        }
        return o;
    }

}

8.3 单条件精确查询

 @PostMapping("singleConditionPreciseQuery")
    public Object singleConditionPreciseQuery(@RequestParam(value = "query") String query) throws Exception {
    
    
        // 创建请求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.matchQuery("name", query));

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("user");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 执行请求
        List<User> users = new ArrayList<>();
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        for (SearchHit searchHit : response.getHits().getHits()) {
    
    
            Map<String, Object> map = searchHit.getSourceAsMap();
            BeanHandler<User> beanHandler = new BeanHandler<>(User.class);
            User user = beanHandler.handle(map);
            users.add(user);
        }
        // 解析查询结果
        return users;
    }

8.4 范围查询

  /**
     * 范围查询
     * 包括from、to
     *
     * @return
     */
    @PostMapping("rangeSearch1")
    public Object rangeSearch1(@RequestParam(value = "from") int from, @RequestParam(value = "to") int to) throws Exception {
    
    
        // 创建请求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.rangeQuery("age").from(from).to(to));

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("user");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 执行请求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查询结果
        // 执行请求
        List<User> users = new ArrayList<>();
        for (SearchHit searchHit : response.getHits().getHits()) {
    
    
            Map<String, Object> map = searchHit.getSourceAsMap();
            BeanHandler<User> beanHandler = new BeanHandler<>(User.class);
            User user = beanHandler.handle(map);
            users.add(user);
        }
        // 解析查询结果
        return users;
    }

    /**
     * 范围查询
     * 不包括from、to
     *
     * @return
     */
    @PostMapping("rangeSearch2")
    public Object rangeSearch2(@RequestParam(value = "from") int from, @RequestParam(value = "to") int to) throws Exception {
    
    
        // 创建请求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.rangeQuery("age").from(from, false).to(to, false));

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("user");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 执行请求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查询结果
        // 执行请求
        List<User> users = new ArrayList<>();
        for (SearchHit searchHit : response.getHits().getHits()) {
    
    
            Map<String, Object> map = searchHit.getSourceAsMap();
            BeanHandler<User> beanHandler = new BeanHandler<>(User.class);
            User user = beanHandler.handle(map);
            users.add(user);
        }
        // 解析查询结果
        return users;
    }

    /**
     * 范围查询
     * lt:小于,gt:大于
     *
     * @return
     */
    @PostMapping("rangeSearch3")
    public Object rangeSearch3(@RequestParam(value = "from") int from, @RequestParam(value = "to") int to) throws Exception {
    
    
        // 创建请求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.rangeQuery("age").lt(to).gt(from));

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("user");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 执行请求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查询结果
        // 执行请求
        List<User> users = new ArrayList<>();
        for (SearchHit searchHit : response.getHits().getHits()) {
    
    
            Map<String, Object> map = searchHit.getSourceAsMap();
            BeanHandler<User> beanHandler = new BeanHandler<>(User.class);
            User user = beanHandler.handle(map);
            users.add(user);
        }
        // 解析查询结果
        return users;
    }

在这里插入图片描述

8.5 模糊查询,支持通配符

    /**
     * 模糊查询,支持通配符
     *
     * @return
     */
    @PostMapping("vagueSearch")
    public Object vagueSearch(@RequestParam(value = "query") String query) throws Exception {
    
    
        // 创建请求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.wildcardQuery("name", query));

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("user");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 执行请求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 执行请求
        List<User> users = new ArrayList<>();
        for (SearchHit searchHit : response.getHits().getHits()) {
    
    
            Map<String, Object> map = searchHit.getSourceAsMap();
            BeanHandler<User> beanHandler = new BeanHandler<>(User.class);
            User user = beanHandler.handle(map);
            users.add(user);
        }
        // 解析查询结果
        return users;
    }

    /**
     * 不使用通配符的模糊查询,左右匹配
     *
     * @return
     */
    @PostMapping("vagueSearch1")
    public Object vagueSearch1(@RequestParam(value = "query") String query) throws Exception {
    
    
        // 创建请求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.queryStringQuery(query).field("name"));

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("user");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 执行请求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 执行请求
        List<User> users = new ArrayList<>();
        for (SearchHit searchHit : response.getHits().getHits()) {
    
    
            Map<String, Object> map = searchHit.getSourceAsMap();
            BeanHandler<User> beanHandler = new BeanHandler<>(User.class);
            User user = beanHandler.handle(map);
            users.add(user);
        }
        // 解析查询结果
        return users;
    }
    /**
     * 多字段模糊查询
     *
     * @return
     */
    @PostMapping("vagueSearch2")
    public Object vagueSearch2(@RequestParam(value = "query") String query) throws Exception {
    
    
        // 创建请求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.multiMatchQuery(query, "name", "info"));

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("user");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 执行请求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 执行请求
        List<User> users = new ArrayList<>();
        for (SearchHit searchHit : response.getHits().getHits()) {
    
    
            Map<String, Object> map = searchHit.getSourceAsMap();
            BeanHandler<User> beanHandler = new BeanHandler<>(User.class);
            User user = beanHandler.handle(map);
            users.add(user);
        }
        // 解析查询结果
        return users;
    }

8.6 排序

 /**
     * 排序
     *
     * @return
     */
    @PostMapping("sortSearch")
    public Object sortSearch(@RequestParam(value = "query") String query) throws Exception {
    
    
        // 创建请求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.multiMatchQuery(query, "name", "info"))
                .sort("age", SortOrder.ASC);//按照年龄正序

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("user");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 执行请求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 执行请求
        List<User> users = new ArrayList<>();
        for (SearchHit searchHit : response.getHits().getHits()) {
    
    
            Map<String, Object> map = searchHit.getSourceAsMap();
            BeanHandler<User> beanHandler = new BeanHandler<>(User.class);
            User user = beanHandler.handle(map);
            users.add(user);
        }
        // 解析查询结果
        return users;
    }

8.7 精确统计筛选文档数

   /**
     * 精确统计筛选文档数,查询性能有所降低
     *
     * @return
     */
    @PostMapping("countSearch")
    public Object countSearch() throws Exception {
    
    
        // 创建请求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .trackTotalHits(true);
        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("user");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 执行请求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查询结果
        return response;
    }

8.8 设置源字段过滤返回

    /**
     * 设置源字段过虑,第一个参数结果集包括哪些字段,第二个参数表示结果集不包括哪些字段
     *
     * @return
     */
    @PostMapping("filterSearch")
    public Object filterSearch() throws Exception {
    
    
        // 创建请求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .fetchSource(new String[]{
    
    "name", "age"}, new String[]{
    
    "id", "info"});
        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("user");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 执行请求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 执行请求
        List<User> users = new ArrayList<>();
        for (SearchHit searchHit : response.getHits().getHits()) {
    
    
            Map<String, Object> map = searchHit.getSourceAsMap();
            BeanHandler<User> beanHandler = new BeanHandler<>(User.class);
            User user = beanHandler.handle(map);
            users.add(user);
        }
        // 解析查询结果
        return users;
    }

在这里插入图片描述

通过上图的结果我们也可以看出:

  • 第一个参数结果集包括哪些字段
  • 第二个参数表示结果集不包括哪些字段

在这里插入图片描述

8.9 根据 id 精确匹配

   /**
     * 根据Id精准查询
     *
     * @return
     */
    @PostMapping("searchByIds")
    public Object searchByIds(@RequestBody Map<String, Object> params) throws Exception {
    
    
        List<Integer> ids = (List<Integer>) params.get("ids");
        // 创建请求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.termsQuery("_id", ids));
        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("user");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 执行请求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 执行请求
        List<User> users = new ArrayList<>();
        for (SearchHit searchHit : response.getHits().getHits()) {
    
    
            Map<String, Object> map = searchHit.getSourceAsMap();
            BeanHandler<User> beanHandler = new BeanHandler<>(User.class);
            User user = beanHandler.handle(map);
            users.add(user);
        }
        // 解析查询结果
        return users;
    }

8.10 matchAllQuery 搜索全部

   /**
     * matchAllQuery 搜索全部
     *
     * @return
     */
    @PostMapping("martchAllQuery")
    public Object martchAllQuery() throws Exception {
    
    
        // 创建请求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.matchAllQuery());
        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("user");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 执行请求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 执行请求
        List<User> users = new ArrayList<>();
        for (SearchHit searchHit : response.getHits().getHits()) {
    
    
            Map<String, Object> map = searchHit.getSourceAsMap();
            BeanHandler<User> beanHandler = new BeanHandler<>(User.class);
            User user = beanHandler.handle(map);
            users.add(user);
        }
        // 解析查询结果
        return users;
    }

8.11 match 搜索匹配

   /**
     * match 搜索匹配
     *
     * @return
     */
    @PostMapping("martch")
    public Object martch(@RequestBody Map<String, Object> params) throws Exception {
    
    
        List<String> querys = (List<String>) params.get("querys");
        // 创建请求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.matchQuery("name", querys));
        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("user");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 执行请求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 执行请求
        List<User> users = new ArrayList<>();
        for (SearchHit searchHit : response.getHits().getHits()) {
    
    
            Map<String, Object> map = searchHit.getSourceAsMap();
            BeanHandler<User> beanHandler = new BeanHandler<>(User.class);
            User user = beanHandler.handle(map);
            users.add(user);
        }
        // 解析查询结果
        return users;
    }

8.12 bool组合查询

    /**
     * bool组合查询
     *
     * @return
     */
    @PostMapping("boolSearch")
    public Object boolSearch(@RequestBody Map<String, Object> params) throws Exception {
    
    
        List<String> queryNames = (List<String>) params.get("names");
        int maxAge = (int) params.get("maxAge");
        int minAge = (int) params.get("minAge");

        // 创建请求
        SearchSourceBuilder builder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        boolQueryBuilder.must(QueryBuilders.termsQuery("name", queryNames));
        boolQueryBuilder.must(QueryBuilders.rangeQuery("age").lte(maxAge).gte(minAge));
        builder.query(boolQueryBuilder);
        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("user");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 执行请求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 执行请求
        List<User> users = new ArrayList<>();
        for (SearchHit searchHit : response.getHits().getHits()) {
    
    
            Map<String, Object> map = searchHit.getSourceAsMap();
            BeanHandler<User> beanHandler = new BeanHandler<>(User.class);
            User user = beanHandler.handle(map);
            users.add(user);
        }
        // 解析查询结果
        return users;
    }

在这里插入图片描述

8.13 nested类型嵌套查询

有时候,我们需要查询一个对象内部类的值,发现通过平时的查询查询不到数据,这时DSL(Domain Specific language,即特定领域专用语言)出场了!

elasticsearch中的内部对象无法按预期工作,这里的问题是elasticsearch(lucene)使用的库没有内部对象的概念,因此内部对象被扁平化为一个简单的字段名称和值列表。

    /**
     * nested类型嵌套查询
     *
     * @return
     */
    @PostMapping("nestedSearch")
    public Object nestedSearch() throws Exception {
    
    
        // 创建请求
        SearchSourceBuilder builder = new SearchSourceBuilder();
        //条件查询
        BoolQueryBuilder mainBool=new BoolQueryBuilder();
        mainBool.must(QueryBuilders.matchQuery("name", "赵六"));
        //nested类型嵌套查询
        BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder();
        boolQueryBuilder.must(QueryBuilders.matchQuery("user.name", "A"));
        boolQueryBuilder.must(QueryBuilders.matchQuery("user.info", "浦东"));
        NestedQueryBuilder nested = QueryBuilders.nestedQuery("user",boolQueryBuilder, ScoreMode.None);
        mainBool.must(nested);
        builder.query(mainBool);
        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("user");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 执行请求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 执行请求
        List<User> users = new ArrayList<>();
        for (SearchHit searchHit : response.getHits().getHits()) {
    
    
            Map<String, Object> map = searchHit.getSourceAsMap();
            BeanHandler<User> beanHandler = new BeanHandler<>(User.class);
            User user = beanHandler.handle(map);
            users.add(user);
        }
        // 解析查询结果
        return users;
    }

8.14 多条件查询 + 排序 + 分页

    /**
     * 多条件查询 + 排序 + 分页
     *
     * @return
     */
    @PostMapping("multiConditionSearch")
    public Object multiConditionSearch() throws Exception {
    
    
        // 创建请求
        SearchSourceBuilder builder = new SearchSourceBuilder();
        //条件搜索
        BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder();
        boolQueryBuilder.must(QueryBuilders.matchQuery
        ("name", "张").operator(Operator.AND);//需要 满足所有字段);
        boolQueryBuilder.must(QueryBuilders.rangeQuery("age").lte(30).gte(20));
        builder.query(boolQueryBuilder);
        //结果集合分页
        builder.from(0).size(2);

        //排序
        builder.sort("age",SortOrder.ASC);
        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("user");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 执行请求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 执行请求
        List<User> users = new ArrayList<>();
        for (SearchHit searchHit : response.getHits().getHits()) {
    
    
            Map<String, Object> map = searchHit.getSourceAsMap();
            BeanHandler<User> beanHandler = new BeanHandler<>(User.class);
            User user = beanHandler.handle(map);
            users.add(user);
        }
        // 解析查询结果
        return users;
    }

8.15 聚合查询

   /**
     * 求和
     *
     * @return
     */
    @PostMapping("sumSearch")
    public Object sumSearch() throws Exception {
    
    
        Map<String, Object> result = new HashMap<>();
        // 创建请求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.termsQuery("_id", new int[]{
    
    1, 2, 3}));
        //条件搜索
        //结果集合分页
        builder.from(0).size(2);
        builder.query(QueryBuilders.matchAllQuery());
        //聚合查询
        AggregationBuilder aggregation = AggregationBuilders.sum("sum_age").field("age");
        builder.aggregation(aggregation);

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("user");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 执行请求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查询结果
        return response;
    }

在这里插入图片描述

在这里插入图片描述

值得我们注意的是在进行聚合操作的fild上,如果我们该字段设置成key或者text,则会出现以下错误
在这里插入图片描述

原因是:

文本字段未针对需要每个文档字段数据(如聚合和排序)的操作进行优化,因此默认情况下禁用这些操作。

我们需要改用关键字字段。或者,在设置了text或者key的字段上设置fielddata=true,以便通过取消反转索引来加载字段数据。

请注意,这可能会占用大量内存


git地址:https://gitee.com/ninesuntec/es-better.git

PS:本章git上的代码如果有被注释掉的,只是为了防止和后面的章节不冲突,并无错误,大家自行解注查看即可

猜你喜欢

转载自blog.csdn.net/zhiyikeji/article/details/128939901