Elastic Stack--09--ElasticsearchRestTemplate

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


spring-data-elasticsearch

  • spring-data-elasticsearch是比较好用的一个elasticsearch客户端,本文介绍如何使用它来操作ES。本文使用spring-boot-starter-data-elasticsearch,它内部会引入spring-data-elasticsearch。

提供的API

Spring Data ElasticSearch有下边这几种方法操作ElasticSearch:

  • ElasticsearchRepository(传统的方法,可以使用)
  • ElasticsearchRestTemplate(推荐使用。基于RestHighLevelClient)
  • ElasticsearchTemplate(ES7中废弃,不建议使用。基于TransportClient)
  • RestHighLevelClient(推荐度低于ElasticsearchRestTemplate,因为API不够高级)
  • TransportClient(ES7中废弃,不建议使用)

QueryBuilders

QueryBuilders是ES中的查询条件构造器

  • QueryBuilders.boolQuery #子方法must可多条件联查

  • QueryBuilders.termQuery #精确查询指定字段

  • QueryBuilders.matchQuery #按分词器进行模糊查询

  • QueryBuilders.rangeQuery #按指定字段进行区间范围查询

ElasticsearchRestTemplate 方法

ElasticsearchRestTemplate ---操作索引

java 复制代码
/**
 * 测试boot整合es
 */
@SpringBootTest(classes = {SpringbootEsApplication.class})
@RunWith(SpringRunner.class)
public class testES {

    @Autowired
    private ElasticsearchRestTemplate restTemplate;


        /**
	     * 创建索引,并设置映射。
	     * 需要通过两次访问实现,1、创建索引;2、设置映射。
	     */
	    @Test
	    public void testInitIndex(){
	        // 创建索引,根据类型上的Document注解创建
	        boolean isCreated = restTemplate.createIndex(Item.class);
	        // 设置映射,根据属性上的Field注解设置 0201
	        boolean isMapped = restTemplate.putMapping(Item.class);
	        System.out.println("创建索引是否成功:" + isCreated);
	        System.out.println("设置映射是否成功:" + isMapped);
	    }
	    
    /**
     * 删除索引
     */
    @Test
    public void deleteIndex(){
        // 扫描Item类型上的Document注解,删除对应的索引。
        boolean isDeleted = restTemplate.deleteIndex(Item.class);
        System.out.println("删除Item对应索引是否成功:" + isDeleted);
        // 直接删除对应名称的索引。
        isDeleted = restTemplate.deleteIndex("test_index3");
        System.out.println("删除default_index索引是否成功:" + isDeleted);
    }

}

ElasticsearchRestTemplate ---文档操作

1.新增文档

  • 如果索引和类型不存在,也可以执行进行新增,新增后自动创建索引和类型。但是 field 通过动态 mapping进行映射,elaticsearch 根据值类型进行判断每个属性类型,默认每个属性都是 standard 分词器,ik分词器是不生效的。所以一定要先通过代码进行初始化或直接在 elasticsearch 中通过命令创建所有 field 的 mapping
  • 如果对象的 id 属性没有赋值,让 ES 自动生成主键,存储时 id 属性没有值,_id 存储 document 的主键值。 如果对象的 id 属性明确设置值,存储时 id 属性为设置的值,ES 中 document 对象的 _id 也是设置的值

index()

index逻辑,相当于使用PUT请求,实现数据的新增

java 复制代码
    /**
     * 新增数据到ES
     */
    @Test
    public void testInsert(){
        Item item = new Item();
        item.setId("19216811");
        item.setTitle("沃什.伊戈.史莱姆");
        item.setSellPoint("关于我成为史莱姆却因为铺垫太长遭人骂这档事");
        item.setPrice(996666L);
        item.setNum(233);

        //方式 1:这个是构建器放入的方式
        IndexQuery indexQuery = new IndexQueryBuilder() // 创建一个IndexQuery的构建器
                                    .withObject(item) // 设置要新增的Java对象
                                    .build(); // 构建IndexQuery类型的对象。
        
         //方式 2: 这个是直接放入的方式
//        IndexQuery query = new IndexQuery();
//        query.setObject(item);


        // index逻辑,相当于使用PUT请求,实现数据的新增。
        String result = restTemplate.index(indexQuery);
        System.out.println(result);
    }

批量新增,使用的是bulkIndex() 操作

java 复制代码
/**
     * 批量新增
     * bulk操作
     */
    @Test
    public void testBatchInsert(){
        List<IndexQuery> queries = new ArrayList<IndexQuery>();
        Item item = new Item();
        item.setId("20210224");
        item.setTitle("IPHONE 12 手机");
        item.setSellPoint("很贵");
        item.setPrice(499900L);
        item.setNum(999);
        queries.add(new IndexQueryBuilder().withObject(item).build());
        item = new Item();
        item.setId("20210225");
        item.setTitle("华为P40照相手机");
        item.setSellPoint("可以拍月亮");
        item.setPrice(599900L);
        item.setNum(999);
        queries.add(new IndexQueryBuilder().withObject(item).build());
        item = new Item();
        item.setId("20210226");
        item.setTitle("红米k30");
        item.setSellPoint("大品牌值得信赖");
        item.setPrice(699900L);
        item.setNum(999);
        queries.add(new IndexQueryBuilder().withObject(item).build());
        // 批量新增,使用的是bulk操作。
        restTemplate.bulkIndex(queries);
    }

save()

java 复制代码
    /**
     * 新增单个文档
     */
    @Test
    void insert(){
        Student student = new Student();
        student.setAge(23);
        student.setData("123");
        student.setDesc("华为手机");
        student.setId("1");
        student.setName("张三");
        Student save = elasticsearchRestTemplate.save(student);
        System.out.println(save);
    }
    
    /**
     * 批量新增
     */
    @Test
    void batchInsert(){
        List<Student> list = new ArrayList<>();
        list.add(new Student("2","李四","苹果手机","1",22));
        list.add(new Student("3","王五","oppo手机","2",24));
        list.add(new Student("4","赵六","voio手机","3",25));
        list.add(new Student("5","田七","小米手机","4",26));
        Iterable<Student> result = elasticsearchRestTemplate.save(list);
        System.out.println(result);
    }

2.删除文档

  • 根据主键删除 delete(String indexName,String typeName,String id);通过字符串指定索引,类型 和 id 值delete(Class,String id)第一个参数传递实体类类类型,建议使用此方法,减少索引名 和类型名由于手动编写出现错误的概率。 返回值为 delete 方法第二个参数值(删除文档的主键值)
java 复制代码
    /**
     * 删除文档
     */
    @Test
    public void testDelete(){
        // 根据主键删除, 常用
        String result = restTemplate.delete(Item.class, "192168111");
        System.out.println(result);

        // 根据查询结果,删除查到的数据。 应用较少。
        DeleteQuery query = new DeleteQuery();
        query.setIndex("hrt-item");
        query.setType("item");
        query.setQuery(QueryBuilders.matchQuery("title", "沃什.伊戈.史莱姆1"));
        restTemplate.delete(query, Item.class);
    }
java 复制代码
   /**
     * 根据查询条件删除
     */
    @Test
    void  delete() {
        QueryStringQueryBuilder queryBuilder = QueryBuilders.queryStringQuery("张三");
        Query query = new NativeSearchQuery(queryBuilder);
        ByQueryResponse QueryDelete = elasticsearchRestTemplate.delete(query, Student.class);
        System.out.println(QueryDelete);
    }

3.修改文档

  • 修改操作就是新增代码,只要保证主键 id 已经存在,新增就是修改。
  • 如果使用部分更新,则需要通过 update 方法实现。具体如下

全量替换

java 复制代码
   /**
     * 批量修改
     */
    @Test
    void update(){
        Student student = new Student();
        student.setId("1");
        student.setAge(23);
        student.setData("99");
        student.setDesc("华为手机AND苹果手机");
        student.setName("张三");
        Student save = elasticsearchRestTemplate.save(student);
        System.out.println(save);
    }

部分修改

java 复制代码
    /**
     * 部分修改
     */
    @Test
    void update2(){
        // ctx._source 固定写法
        String script = "ctx._source.age = 27;ctx._source.desc = 'oppo手机and苹果电脑'";
        UpdateQuery build = UpdateQuery.builder("3").withScript(script).build();
        IndexCoordinates indexCoordinates = IndexCoordinates.of("student_index");
        UpdateResponse update = elasticsearchRestTemplate.update(build, indexCoordinates);
        System.out.println(update.getResult());
    }
java 复制代码
/**
     * 修改文档
     * 如果是全量替换,可以使用index方法实现,只要主键在索引中存在,就是全量替换。<=>新增or批量新增操作
     * 如果是部分修改,则可以使用update实现。
     */
    @Test
    public void testUpdate() throws Exception{
        UpdateRequest request = new UpdateRequest();
        request.doc(
                XContentFactory.jsonBuilder()
                        .startObject()
                        .field("name", "测试update更新数据,商品名称")
                        .endObject()
        );
        UpdateQuery updateQuery =
                new UpdateQueryBuilder()
                        .withUpdateRequest(request)
                        .withClass(Item.class)
                        .withId("20210224")
                        .build();
        restTemplate.update(updateQuery);
    }

ElasticsearchRestTemplate --- 文档查询

query 原理分析:

java 复制代码
        SearchQuery query = new NativeSearchQuery(QueryBuilders.matchQuery("title", "华为mate40"));
        List<Item> itemList = restTemplate.queryForList(query, Item.class);
  1. SearchQuery - 是Spring Data Elasticsearch中定义的一个搜索接口

  2. NativeSearchQuery - 是SearchQuery接口的实现类 ,构造的时候,需要提供一个QueryBuilder类型的对象

  3. QueryBuilder是Elasticsearch的java客户端中定义的搜索条件类型。

  4. QueryBuilders - 是QueryBuilder类型的工具类,可以快速实现QueryBuilder类型对象的创建工具类中,提供了大量的静态方法,方法命名和DSL搜索中的条件关键字相关。

NativeSearchQuery---查询条件类

new NativeSearchQuery(, , ,)


  • 原生的查询条件类,用来和ES的一些原生查询方法进行搭配,实现一些比较复杂的查询,最终进行构建.build
    可作为ElasticsearchTemplate. queryForPage的参数使用
java 复制代码
//构建Search对象
        NativeSearchQuery query = new NativeSearchQueryBuilder()
                //条件
                .withQuery(QueryBuilders.matchQuery("title", "华为mate40"))
                //排序
                .withSort(SortBuilders.fieldSort("id").order(SortOrder.ASC))
                //高亮
                .withHighlightFields(name, ms)
                //分页
                .withPageable(PageRequest.of(pageNum - 1, pageSize))
                //构建
                .build();
 
         //queryForPage 参数一: NativeSearchQuery 封装的查询数据对象
         //            参数二: es对应索引实体类
        //            参数三: 调用高亮工具类
        AggregatedPage<Goods> aggregatedPage = elasticsearchTemplate.queryForPage(query , Goods.class,new Hig());
 

1.只查询一个id的 (idsQuery)

只查询一个id的

java 复制代码
    @Autowired
    private ElasticsearchRestTemplate restTemplate; 
    
    /*
     * 只查询一个id的
     * QueryBuilders.idsQuery(String...type).ids(Collection<String> ids)
     */
    @Test
    public void testIdsQuery() {
        QueryBuilder query = QueryBuilders.idsQuery().ids("1");
         List<Item> itemList = restTemplate.queryForList(query, Item.class);
    }

2.模糊搜索( matchQuery )

  • matchQuery("key", Obj) 单个匹配, field不支持通配符, 前缀具高级特性
  • multiMatchQuery("text", "field1", "field2"...); 匹配多个字段, field有通配符忒行
  • matchAllQuery(); 匹配所有文件
  • matchAllQuery() 搜索所有数据

去所有 field 中搜索指定条件。

  • 在kibana的dev tools中修改之前批量新增的一个数据, 目的是当我们搜索华为Mate40 时, 不仅能够搜索到
java 复制代码
    /**
     * 条件搜索
     */
    @Test
    public void testMatch(){
        SearchQuery query = new NativeSearchQuery(QueryBuilders.matchQuery("title", "华为mate40"));
        List<Item> itemList = restTemplate.queryForList(query, Item.class);
    }

operator

如果想使用一个字段匹配多个值,并且这多个值是and关系,如下 要求查询的数据中必须包含北京'和'天津

  • QueryBuilders.matchQuery("address","北京 天津").operator(Operator.AND)

如果想使用一个字段匹配多个值,并且这多个值是or关系,如下 要求查询的数据中必须包含北京'或'天津

  • QueryBuilders.matchQuery("address","北京 天津").operator(Operator.OR)

multiMatchQuery

QueryBuilders.multiMatchQuery() 会分词 一个值对应多个字段 where username = 'zs' or password = 'zs'

java 复制代码
 /**
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * multimatch  query
     * 创建一个匹配查询的布尔型提供字段名称和文本。
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder multiMatchQuery() {
        //现住址和家乡在【山西省太原市7429街道】的人
        return QueryBuilders.multiMatchQuery(
                "zs",     // Text you are looking for
                "username ", "password "       // Fields you query on
        );
    }

短语搜索--- matchPhraseQuery

QueryBuilders.matchPhraseQuery() 不会分词,当成一个整体去匹配,相当于 %like%

短语搜索是对条件不分词,但是文档中属性根据配置实体类时指定的分词类型进行分词。

  • 如果属性使用 ik 分词器,从分词后的索引数据中进行匹配。
java 复制代码
	/**
     * 短语搜索
     * 只要被分词后锁短语含有, 则都会被搜索到
     */
    @Test
    public void testMatchPhrase(){
        SearchQuery query = new NativeSearchQuery(QueryBuilders.matchPhraseQuery("title", "华为mate40"));
        
        List<Item> itemList = restTemplate.queryForList(query, Item.class);

    }

搜索所有数据---matchAllQuery

java 复制代码
   
   /**
     * 搜索所有数据
     */
    @Test
    public void testMatchAll(){
        SearchQuery query = new NativeSearchQuery(QueryBuilders.matchAllQuery());
        List<Item> itemList = restTemplate.queryForList(query, Item.class);
    }

3.词组搜索--精确查询指定字段(termQuery)

java 复制代码
	/**
     * 词组搜索
     * 只有没有被切分的词组才能搜到结果, 例如: 华为荣耀已被切分, 则搜索不到; 而荣耀 不会被切分因此能够搜索到结果
     * 区别于短语搜索
     */
    @Test
    public void testTerm(){
        SearchQuery query = new NativeSearchQuery(QueryBuilders.termQuery("title", "mate40"));
        List<Item> itemList = restTemplate.queryForList(query, Item.class);
    }

termsQuery

一个查询相匹配的多个value

java 复制代码
/**
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * terms query
     * 一个查询相匹配的多个value
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder termsQuery() {
        return QueryBuilders.termsQuery("name", // field
                "葫芦580娃", "葫芦3812娃")                 // values
                .minimumMatch(1);               // 设置最小数量的匹配提供了条件。默认为1。
    }

    protected static QueryBuilder termsQuery1() {
          List<Long> channelIdList =new ArrayList<>();
       return  QueryBuilders.termsQuery("channel.channelId", channelIdList);
    }

mathcQuery与termQuery区别:

  • matchQuery:会将搜索词分词,再与目标查询字段进行匹配,若分词中的任意一个词与目标字段匹配上,则可查询到。
  • termQuery:不会对搜索词进行分词处理,而是作为一个整体与目标字段进行匹配,若完全匹配,则可查询到
QueryBuilders.termQuery ------精确查询指定字段
QueryBuilders.matchQuery ------ 按分词器进行模糊查询

4.范围搜索(rangeQuery)

java 复制代码
/**
     * 范围搜索 range
     * gte <==> 小于等于 ; gt <==> 小于 
     * lte <==> 大于等于 ; lt <==> 大于
     */
    @Test
    public void testRange(){
        SearchQuery query = new NativeSearchQuery(
                QueryBuilders.rangeQuery("price").gte(500000L).lte(400000L)
        );
        List<Item> itemList = restTemplate.queryForList(query, Item.class);
    }

5.复合条件搜索 (boolQuery)

  • must(QueryBuilders) : AND
  • mustNot(QueryBuilders): NOT
  • should : OR
  • filter : 过滤
java 复制代码
    /**
     * 复合条件搜索
     */
    @Test
    public void testBool(){
        // 创建一个Bool搜索条件。 相当于定义 bool:{ must:[], should:[], must_not:[] }
        BoolQueryBuilder builder = QueryBuilders.boolQuery();
        List<QueryBuilder> mustList = builder.must();
        //词组所搜+范围搜索
        mustList.add(QueryBuilders.matchQuery("title", "华为"));
        mustList.add(QueryBuilders.rangeQuery("price").gte(300000L));
        // builder.mustNot();
        // builder.should();
        SearchQuery query = new NativeSearchQuery(builder);
        List<Item> itemList = restTemplate.queryForList(query, Item.class);

    }
java 复制代码
    /**
     *  多条件查询
     */
    @Test
    void querysSearch(){
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        List<QueryBuilder> listQuery = new ArrayList<>();
        listQuery.add(QueryBuilders.matchQuery("name","张三"));
        listQuery.add(QueryBuilders.matchQuery("age","23"));
    
        boolQueryBuilder.must().addAll(listQuery);// 逻辑 与
//        boolQueryBuilder.should().addAll(listQuery);// 逻辑 或
       
         NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(boolQueryBuilder );
         SearchHits<Student> search = elasticsearchRestTemplate.search(nativeSearchQuery, Student.class);
        List<SearchHit<Student>> searchHits = search.getSearchHits();

    }

查询address 必须包含'汽车' 或者'水果'的,查询id必须不能包含'2'和'0'的。此时需要构造两个条件,

  • 类似mysql中的 where (address like %汽车% oraddress like %水果% ) and (id != 1 or id != 2)
java 复制代码
@Test
	public void testBoolQuery() throws IOException {
		SearchRequest searchRequest = new SearchRequest(indexName);
		SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
 
		BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
		boolQuery.must(QueryBuilders.matchQuery("address","水果 汽车").operator(Operator.OR));
		boolQuery.mustNot(QueryBuilders.termsQuery("id","0","2"));
		searchSourceBuilder.query(boolQuery);
 
		searchRequest.source(searchSourceBuilder);
 
		SearchResponse search = client.search(searchRequest, ElasticSearchConfig.COMMON_OPTIONS);
		for (SearchHit documentFields : search.getHits().getHits()) {
			System.out.println(documentFields.getScore() + ":::"  +documentFields.getSourceAsString());
		}
	}
java 复制代码
    /**
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * boolean query and 条件组合查询
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder booleanQuery() {
 
        return QueryBuilders
                .boolQuery()
                .must(QueryBuilders.termQuery("name", "葫芦3033娃"))
                .must(QueryBuilders.termQuery("home", "山西省太原市7967街道"))
                .mustNot(QueryBuilders.termQuery("isRealMen", false))
                .should(QueryBuilders.termQuery("now_home", "山西省太原市"));
    }

6.过滤 ( boolQueryBuilder.filter)

  • must:返回的文档必须满足must子句的条件,并且参与计算分值
  • filter:返回的文档必须满足filter子句的条件。但是跟Must不一样的是,不会计算分值, 并且可以使用缓存

从上面的描述来看,你应该已经知道,如果只看查询的结果,must和filter是一样的。区别是场景不一样。如果结果需要算分就使用must,否则可以考虑使用filter。

filter查询就是用于精确过滤文档,它只关注文档是否符合条件,将匹配的文档包含在结果中。他们都不进行打分、排序或相关性计算,只担心是否匹配

  • 品牌和类目的过滤
java 复制代码
//2、根据类目ID进行过滤
if (null != param.getCategoryId()) {
    boolQueryBuilder.filter(QueryBuilders.termQuery("categoryId", param.getCategoryId()));
}
 
//3、根据品牌ID进行过滤
if (null != param.getBrandId() && param.getBrandId().size() > 0) {
    boolQueryBuilder.filter(QueryBuilders.termsQuery("brandId", param.getBrandId()));
}
  • 是否有库存
java 复制代码
if (null != param.getHasStock()) {
    boolQueryBuilder.filter(QueryBuilders.termQuery("hasStock", param.getHasStock() == 1));
}

7.分页和排序搜索

如果实体类中主键只有@Id 注解,String id 对应 ES 中是 text 类型,text 类型是不允许被排序,

  • 所以如果必须按照主键进行排序时需要在实体类中设置主键类型@Id @Field(type = FieldType.Keyword)
    private String id;
java 复制代码
/**
     * 分页和排序
     * 所有的Spring Data子工程中的分页和排序逻辑使用的都是相似的方式。
     * 根据PageRequest和Sort实现分页或排序。
     */
    @Test
    public void testPageable(){
        SearchQuery query = new NativeSearchQuery(QueryBuilders.matchAllQuery());
        // 设置分页
        query.setPageable(PageRequest.of(0, 2));
        // 设置排序
        query.addSort(Sort.by(Sort.Direction.DESC, "price"));
        // 设置分页的同时设置排序
        // query.setPageable(PageRequest.of(0, 2, Sort.by(Sort.Direction.DESC, "price")))
        List<Item> itemList = restTemplate.queryForList(query, Item.class);
    }
java 复制代码
//构建Search对象
        NativeSearchQuery query = new NativeSearchQueryBuilder()
                //条件
                .withQuery(QueryBuilders.matchQuery("title", "华为mate40"))
                //排序
                .withSort(SortBuilders.fieldSort("id").order(SortOrder.ASC))
                //高亮
                .withHighlightFields(name, ms)
                //分页
                .withPageable(PageRequest.of(pageNum - 1, pageSize))
                //构建
                .build();
 
         //queryForPage 参数一: NativeSearchQuery 封装的查询数据对象
         //            参数二: es对应索引实体类
        //            参数三: 调用高亮工具类
        AggregatedPage<Goods> aggregatedPage = elasticsearchTemplate.queryForPage(query , Goods.class,new Hig());

8.高亮搜索

java 复制代码
	/**
     * 高亮
     */
    @Test
    public void testHighlight(){
        HighlightBuilder.Field field = new HighlightBuilder.Field("title");
        field.preTags("<em>");
        field.postTags("</em>");

        NativeSearchQuery query =
                new NativeSearchQueryBuilder()
                        // 排序
                        .withSort(SortBuilders.fieldSort("price").order(SortOrder.ASC))
                        // 分页
                        .withPageable(PageRequest.of(0, 2))
                        // 搜索条件
                        .withQuery(QueryBuilders.matchQuery("title", "华为"))
                        // 设置高亮字段
                        .withHighlightFields(field)
                        .build();

        AggregatedPage<? extends Item> pageResult =
                restTemplate.queryForPage(query, Item.class, new SearchResultMapper() {
                    // 处理搜索结果,搜索的完整结果,也就是那个集合。
                    // response - 就是搜索的结果,相当于在Kibana中执行搜索的结果内容。
                    // clazz - 就是返回结果的具体类型
                    // pageable - 分页处理,就是queryForPage方法参数query中的pageable对象。
                    public <T> AggregatedPage<T> mapResults(SearchResponse response,
                                                            Class<T> clazz,
                                                            Pageable pageable) {
                        // 获取搜索的结果数据
                        SearchHit[] hits = response.getHits().getHits();
                        List<T> resultList = new ArrayList<T>();
                        for(SearchHit hit : hits){
                            // 搜索的source源
                            Map<String, Object> map = hit.getSourceAsMap();
                            Item item = new Item();
                            item.setId(map.get("id").toString());
                            item.setSellPoint(map.get("sellPoint").toString());
                            item.setPrice(Long.parseLong(map.get("price").toString()));
                            item.setNum(Integer.parseInt(map.get("num").toString()));
                            // 高亮数据处理。key - 字段名, value - 是高亮数据结果
                            Map<String, HighlightField> highlightFieldMap = hit.getHighlightFields();
                            HighlightField highlightField = highlightFieldMap.get("title");
                            if (highlightField == null){ // 没有高亮的title
                                item.setTitle(map.get("title").toString());
                            }else{ // 有高亮的title
                                item.setTitle(highlightField.getFragments()[0].toString());
                            }
                            resultList.add((T)item);
                        }
                       // 返回处理后的结果

                        return new AggregatedPageImpl<T>(
                                resultList, pageable, response.getHits().getTotalHits()
                        );
                    }

                    // 不提供实现,这个是处理每个搜索结果的方法
                    public <T> T mapSearchHit(SearchHit searchHit, Class<T> type) {
                        return null;
                    }
                });

        for(Item item : pageResult.getContent()){
            System.out.println(item);
        }
    }

9. 嵌套查询(nestedQuery)


java 复制代码
 

    /**
     * TODO NotSolved
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * nested query
     * 嵌套查询
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    protected static QueryBuilder nestedQuery() {
        return QueryBuilders.nestedQuery("location",               // Path
                QueryBuilders.boolQuery()                      // Your query
                        .must(QueryBuilders.matchQuery("location.lat", 0.962590433140581))
                        .must(QueryBuilders.rangeQuery("location.lon").lt(0.00000000000000000003))
        )
                .scoreMode("total");                  // max, total, avg or none
相关推荐
摸鱼也很难11 分钟前
Docker 镜像加速和配置的分享 && 云服务器搭建beef-xss
运维·docker·容器
woshilys1 小时前
sql server 查询对象的修改时间
运维·数据库·sqlserver
疯狂飙车的蜗牛1 小时前
从零玩转CanMV-K230(4)-小核Linux驱动开发参考
linux·运维·驱动开发
恩爸编程2 小时前
探索 Nginx:Web 世界的幕后英雄
运维·nginx·nginx反向代理·nginx是什么·nginx静态资源服务器·nginx服务器·nginx解决哪些问题
Michaelwubo3 小时前
Docker dockerfile镜像编码 centos7
运维·docker·容器
好像是个likun4 小时前
使用docker拉取镜像很慢或者总是超时的问题
运维·docker·容器
cominglately6 小时前
centos单机部署seata
linux·运维·centos
coder_pig6 小时前
📝小记:Ubuntu 部署 Jenkins 打包 Flutter APK
flutter·ubuntu·jenkins
CircleMouse6 小时前
Centos7, 使用yum工具,出现 Could not resolve host: mirrorlist.centos.org
linux·运维·服务器·centos
Karoku0667 小时前
【k8s集群应用】kubeadm1.20高可用部署(3master)
运维·docker·云原生·容器·kubernetes