SpringBoot使用ElasticSearch

news2024/11/26 10:41:35

ES官网:https://www.elastic.co/cn/downloads/elasticsearch

ES下载地址:https://www.elastic.co/cn/downloads/past-releases#elasticsearch

kibana官网:https://www.elastic.co/cn/downloads/kibana

kibana下载地址:https://www.elastic.co/cn/downloads/past-releases#kibana

下载完成后,进入到bin目录下 双击即可运行
在这里插入图片描述
运行完成后访问地址http://127.0.0.1:9200
出现返回的JSON数据 说明已启动,并可以正常使用
在这里插入图片描述

环境

系统环境:Win10
开发环境:IDEA2022.2、JDK8、Apache-Maven-3.8.6
ElasticSearch:ElasticSearch-7.16.0

以下SpringBoot对ElasticSearch的分词、分组、分词高亮、分页、范围、新增、修改操作,完整代码如下,代码复制粘贴即可运行测试学习

1、使用ElasticsearchRepository + ElasticsearchRestTemplate 实现来对ElasticSearch数据的操作

目录结构

在这里插入图片描述

引入项目依赖

创建SpringBoot项目,引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.7</version>
        <relativePath/>
    </parent>

    <groupId>cn.molu.es</groupId>
    <artifactId>ElasticSearch</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>SpringBoot-ElasticSearch</name>
    <description>ElasticSearch</description>

    <properties>
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!--        <elasticsearch.version>7.16.0</elasticsearch.version>-->
    </properties>

    <dependencies>
    	<!-- SpringBoot整合ElasticSearch -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
		
		<!-- Spring整合ElasticSearch -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-elasticsearch</artifactId>
            <version>4.3.4</version>
        </dependency>

		<!-- SpringMvc的Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

		<!-- Lombok简化实体类 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

		<!-- SpringBoot热部署 -->	
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        
        <!-- JSON工具 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.25</version>
        </dependency>

		<!-- SpringBoot配置依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

配置文件

spring: 
  elasticsearch:
#    port: 9200
#    host: 127.0.0.1
    host-port: 127.0.0.1:9200

配置类

/**
 * @ApiNote: ElasticSearch配置类
 * @Author: 陌路
 * @Date: 2023/4/11 22:00
 * @Tool: Created by IntelliJ IDEA
 * * ElasticsearchRestTemplate基于RestHighLevelClient客户端的。
 * * 需要自定义配置类,继承AbstractElasticsearchConfiguration,
 * * 并实现elasticsearchClient()抽象方法,创建RestHighLevelClient对象。
 */
@Data
@Configuration
public class ElasticsearchConfig extends AbstractElasticsearchConfiguration {
    @Value("${spring.elasticsearch.host-port}")
    private String hostPort; // 127.0.0.1:9200

    /**
     * 重写父类方法
     */
    @Bean
    @Override
    public RestHighLevelClient elasticsearchClient() {
        final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo(hostPort)
                .build();
        return RestClients.create(clientConfiguration).rest();
    }
}

Procuct实体对象

/**
 * @ApiNote: Product实体类
 * @Author: 陌路
 * @Date: 2023/4/11 22:03
 * @Tool: Created by IntelliJ IDEA
 * @desc @Document将这个类对象转为 es 中一条文档进行录入
 * @desc indexName: 用来指定文档的索引名称
 * @desc createIndex: 用来指定是否创建索引,默认为true
 */
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Document(indexName = "products")
public class Product implements Serializable {
    private static final long serialVersionUID = -3383480921573039584L;
    /**
     * 必须有 id,这里的 id 是全局唯一的标识,等同于 es 中的"_id"
     * analyzer : 分词器类型
     * index : 是否索引(默认:true)
     * Keyword : 短语,不进行分词
     */
    //商品唯一标识
    @Id
    private Long id;
    //分类名称
    @Field(type = FieldType.Keyword)
    private String category;
    //图片地址
    @Field(type = FieldType.Keyword, index = false)
    private String images;
    // 标题
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String title;
    // 价格
    @Field(type = FieldType.Double)
    private Double price;
    // 创建时间
    @Field(type = FieldType.Date, format = DateFormat.date_optional_time)
    private Date createTime;
    // 描述
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String description;

    public Product(String id, String title, Double price, String description, String category, String images) {
        this.id = Long.valueOf(id);
        this.title = title;
        this.price = price;
        this.category = category;
        this.images = images;
        this.description = description;
        this.createTime = new Date();
    }
}

ProductRepository操作ElasticSearch

/**
 * @ApiNote: ProductRepository操作ElasticSearch
 * @Author: 陌路
 * @Date: 2023/4/11 22:03
 * @Tool: Created by IntelliJ IDEA
 */
@Repository
public interface ProductRepository extends ElasticsearchRepository<Product, Long> {}

搜索控制器

/**
 * @ApiNote: ElasticSearch搜索
 * @Author: 陌路
 * @Date: 2023/4/24 23:17
 * @Tool: Created by IntelliJ IDEA
 */
@RestController
@RequestMapping("/search/")
public class SearchController {

    @Autowired
    private ProductRepository productRepository;
    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
    @Autowired
    @Qualifier("elasticsearchClient")
    private RestHighLevelClient restHighLevelClient;

    private static final Map<String, Object> RESULT = new HashMap<>(2);

    /**
     * 根据id获取ES中的数据
     */
    @GetMapping("{id}")
    public Map<String, Object> queryById(@PathVariable("id") Long id) {
        return result(findById(id));
    }

    /**
     * 获取所有
     */
    @GetMapping("queryAll")
    public Map<String, Object> queryAll() {
        return result(productRepository.findAll());
    }

    /**
     * 新增数据|更新数据(存在就修改,否则就新增)
     */
    @PostMapping("update")
    public Map<String, Object> updateUserLocation(@RequestBody Map<String, Object> param) {
        if (ObjectUtils.isEmpty(param)) return result(null);
        return result(this.updateProduct(getProduct(param)));
    }

    /**
     * 批量新增数据
     */
    @PostMapping("batchAdd")
    public Map<String, Object> batchAdd(@RequestBody Map<String, Object> param) {
        if (ObjectUtils.isEmpty(param)) return result(null);
        Product product = getProduct(param);
        List<Product> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(setProduct(product, i));
        }
        return result(productRepository.saveAll(list));
    }

    /**
     * 根据id删除
     */
    @DeleteMapping("{id}")
    public Map<String, Object> deleteById(@PathVariable("id") Long id) {
        productRepository.deleteById(id);
        return result(id);
    }

    /**
     * 分页查询
     * @param page     当前页码,从0开始
     * @param pageSize 每页显示的条数
     */
    @GetMapping("pageQuery/{page}/{pageSize}")
    public Map<String, Object> pageQuery(@PathVariable("page") Integer page, 	
    									 @PathVariable("pageSize") Integer pageSize) {
        //设置排序(排序方式,正序还是倒序,排序的 id)
        Sort sort = Sort.by(Sort.Direction.DESC, "id");
        //设置分页参数
        PageRequest pageRequest = PageRequest.of(page, pageSize, sort);
        //分页查询数据
        Page<Product> productPage = productRepository.findAll(pageRequest);
        return result(productPage);
    }

    /**
     * 根据标题分词查询数据
     * @param title 词条
     */
    @GetMapping("termQuery")
    public Map<String, Object> termQuery(@RequestParam("title") String title) {
        //构建查询条件
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.should(QueryBuilders.matchQuery("title", title));
        // 构建查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(boolQuery)
                .build();
        //执行查询
        SearchHits<Product> searchHits = elasticsearchRestTemplate.search(searchQuery, Product.class);
        return result(searchHits.getSearchHits());
    }

    /**
     * 根据标题分词查询数据,并高亮显示
     * @param title 词条
     */
    @GetMapping("highLightTermQuery")
    public Map<String, Object> highLightTermQuery(@RequestParam("title") String title) {
        //构建查询条件
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.should(QueryBuilders.matchQuery("title", title));
        //设置高亮字段
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        //设置标签前缀
        highlightBuilder.preTags("<font color='red'>");
        //设置标签后缀
        highlightBuilder.postTags("</font>");
        //设置高亮字段
        highlightBuilder.field("title");
        // 构建查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(boolQuery)
                .withHighlightBuilder(highlightBuilder)
                .build();
        //执行查询
        SearchHits<Product> searchHits = elasticsearchRestTemplate.search(searchQuery, Product.class);
        //获取查询结果
        return result(searchHits.getSearchHits());
    }

    /**
     * 根据标题分词分页查询数据
     * @param title    词条
     * @param page     当前页码,0开始
     * @param pageSize 每页显示的条数
     */
    @GetMapping("termQuery/{page}/{pageSize}")
    public Map<String, Object> termQueryPage(@RequestParam("title") String title,
                                             @PathVariable("page") Integer page,
                                             @PathVariable("pageSize") Integer pageSize) {
        //构建查询条件
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.should(QueryBuilders.matchQuery("title", title));
        //设置排序(排序方式,正序还是倒序,排序的 id)
        Sort sort = Sort.by(Sort.Direction.DESC, "id");
        //设置分页
        PageRequest pageRequest = PageRequest.of(page, pageSize, sort);
        // 构建查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(boolQuery)
                .withPageable(pageRequest)
                .build();
        //执行查询
        SearchHits<Product> searchHits = elasticsearchRestTemplate.search(searchQuery, Product.class);
        return result(searchHits.getSearchHits());
    }

    /**
     * 根据标题分词模糊查询
     * @param title 词条
     */
    @GetMapping("likeTermQueryPage")
    public Map<String, Object> likeTermQueryPage(@RequestParam("title") String title) {
        //构建查询条件
        FuzzyQueryBuilder fuzzyQuery = QueryBuilders.fuzzyQuery("title", title).fuzziness(Fuzziness.ONE);
        // 构建查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(fuzzyQuery)
                .build();
        //执行查询
        SearchHits<Product> searchHits = elasticsearchRestTemplate.search(searchQuery, Product.class);
        return result(searchHits.getSearchHits());
    }

    /**
     * 最大查询
     * @param title 词条查询
     */
    @GetMapping("maxQuery")
    public Map<String, Object> maxQuery(@RequestParam("title") String title) {
        FuzzyQueryBuilder fuzzyQuery = QueryBuilders
        		.fuzzyQuery("title", title)
        		.fuzziness(Fuzziness.ONE);
        // 构建查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(fuzzyQuery)
                .addAggregation(AggregationBuilders.max("maxAge").field("age"))
                .build();
        //执行查询
        SearchHits<Product> searchHits = elasticsearchRestTemplate.search(searchQuery, Product.class);
        //获取查询结果
        return result(searchHits.getSearchHits());
    }

    /**
     * 分组查询
     * @param field 分组字段
     */
    @GetMapping("groupQuery")
    public Map<String, Object> groupQuery(@RequestParam("field") String field) {
    	field = isNull(field,"price");
        // 构建查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .addAggregation(AggregationBuilders
	                .terms("title")
	                .field(field) // 分组字段
                ).build();
        //执行查询
        SearchHits<Product> searchHits = elasticsearchRestTemplate.search(searchQuery, Product.class);
        //获取查询结果
        return result(searchHits.getSearchHits());
    }

    /**
     * 范围查询
     * @param minPrice 最小范围
     * @param maxPrice 最大范围
     * @param field 分组字段
     */
    @GetMapping("rangeQuery")
    public Map<String, Object> rangeQuery(Integer minPrice, Integer maxPrice,String field) {
    	minPrice = isNull(minPrice, 5);
        maxPrice= isNull(maxPrice, 15);
        field = isNull(field,"price");
        //构建条件查询:id为5-15,按价格分组
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.must(QueryBuilders
        	.rangeQuery("id") // 范围字段
        	.from(minPrice) // 最小范围
        	.to(maxPrice) // 最大范围
        );
        // 构建查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(boolQuery)
                .addAggregation(AggregationBuilders
                	.terms("title")
                	.field(field) // 分组字段
                ).build();
        //执行查询
        SearchHits<Product> searchHits = elasticsearchRestTemplate.search(searchQuery, Product.class);
        //获取查询结果
        return result(searchHits.getSearchHits());
    }

    /**
     * 排序查询,所有数据排序
     */
    @GetMapping("sortQuery")
    public Map<String, Object> sortQuery() throws IOException {
        //里面可以放多个索引
        SearchRequest request = new SearchRequest("products");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //按照id倒序排列(score会失效返回NaN)
        sourceBuilder.sort(SortBuilders.fieldSort("_id").order(SortOrder.DESC));
        //执行查询
        SearchResponse response = this.restHighLevelClient.search(request, RequestOptions.DEFAULT);
        //打印结果信息
        org.elasticsearch.search.SearchHits hits = response.getHits();
        //获取查询结果
        return result(hits);
    }

    /**
     * 根据标题分词分页查询,并高亮显示
     *
     * @param title    词条
     * @param page     当前页码,0开始
     * @param pageSize 每页显示的条数
     */
    @GetMapping("highLightTermQueryPage/{page}/{pageSize}")
    public Map<String, Object> highLightTermQueryPage(@RequestParam("title") String title,
                                                      @PathVariable("page") Integer page,
                                                      @PathVariable("pageSize") Integer pageSize) {
        //设置查询分页
        PageRequest pageRequest = PageRequest.of(page, pageSize);
        //构建查询条件
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.should(QueryBuilders.matchQuery("title", title));
        //设置高亮字段
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        //设置标签前缀
        highlightBuilder.preTags("<font color='red'>");
        //设置标签后缀
        highlightBuilder.postTags("</font>");
        //设置高亮字段
        highlightBuilder.field("title");
        // 构建查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(boolQuery)
                .withHighlightBuilder(highlightBuilder)
                .withPageable(pageRequest)
                .build();
        //执行查询
        SearchHits<Product> searchHits = elasticsearchRestTemplate.search(searchQuery, Product.class);
        return result(searchHits.getSearchHits());
    }
	
	// 向ES中添加数据
    private boolean updateProduct(Product product) {
        product = productRepository.save(product);
        if (ObjectUtils.isEmpty(product)) {
            return false;
        }
        return true;
    }
    
	// 根据id向ES中查询数据
    private Product findById(Long id) {
        try {
            Product product = productRepository.findById(id).get();
            return product;
        } catch (Exception e) {
            return null;
        }
    }
	
	// 组装数据,返回Product对象
	public Product setProduct(Product product, int num) {
        Product pro = new Product();
        pro.setId(product.getId() + num);
        pro.setTitle(product.getTitle() + num);
        pro.setPrice(product.getPrice() + num);
        pro.setDescription(product.getDescription() + num);
        pro.setCategory(product.getCategory());
        pro.setImages(product.getImages() + num);
        return pro;
    }

	// 组装数据,返回Product对象
    private static Product getProduct(Map<String, Object> param) {
        String id = String.valueOf(param.get("id"));
        String title = String.valueOf(param.get("title"));
        Double price = Double.valueOf(String.valueOf(param.get("price")));
        String description = String.valueOf(param.get("description"));
        String category = String.valueOf(param.get("category"));
        String images = String.valueOf(param.get("images"));
        Product product = new Product(id, title, price, description, category, images);
        return product;
    }
    
	// 统一向前台返回Map
    private Map<String, Object> result(Object result) {
        RESULT.clear();
        boolean bool = (result instanceof Boolean) ? (Boolean) result : Objects.nonNull(result);
        RESULT.put("code", bool ? 200 : 500);
        RESULT.put("msg", bool ? "success" : "failed");
        RESULT.put("flag", bool);
        RESULT.put("result", result);
        if (bool && result instanceof Collection) {
            Collection coll = (Collection) result;
            RESULT.put("total", coll.size());
        }
        return RESULT;
    }
    
    // 为空时返回指定数据
	private <T> T isNull(Object obj, Object def) {
        return (T) (ObjectUtils.isEmpty(obj) ? def : obj);
    }
}

启动项目并测试

@SpringBootApplication
public class SpringBootElasticSearchApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootElasticSearchApplication.class, args);
    }
}

测试结果

在这里插入图片描述

2、使用ElasticsearchOperations实现对ElasticSearch数据的操作

配置文件和配置类和实体类与上面的案例一致,没有改变

控制器获取参数查询

/**
* @ApiNote: ElasticsearchOperations方式操作ElasticSearch$
* @Author: 陌路
* @Date: 2023/4/25 11:25
* @Tool: Created by IntelliJ IDEA
* 特点:始终使用面向对象方式操作ES
* 索引:用来存放相似文档的集合
* 映射:用来决定放入文档的每个字段以什么样方式录入到ES中,字段类型、字段分词器…
* 文档:可以被索引最小单元,json数据格式
* 使用ElasticsearchOperations进行增删查改操作
*/
@RestController
@RequestMapping("/operation/")
public class ElasticsearchOperationsController {
   @Autowired
   private ElasticsearchOperations elasticsearchOperations;
   private static final Map<String, Object> RESULT = new HashMap<>(2);

   /**
    * 保存新增|修改数据
    * 方法当文档的id不存在时添加文档,当文档id存在时候更新文档
    */
   @PostMapping("save")
   public Map<String, Object> testSave(@RequestBody Map<String,Object> map) {
       List<Product> list = batchProductList(map);
       Iterable iterable = elasticsearchOperations.save(list);
       return result(iterable);
   }

   /**
    * 根据id查询数据
    * @param id 文档id
    */
   @GetMapping("queryById/{id}")
   public Map testQuery(@PathVariable("id") String id) {
       Product product = elasticsearchOperations.get(id, Product.class);
       System.out.println(product);
       return result(product);
   }

   /**
    * 根据id删除一条文档
    * @param id 文档id
    */
   @DeleteMapping("deleteById/{id}")
   public Map testDelete(@PathVariable("id") Long id) {
       Product product = new Product();
       product.setId(id);
       String delete = elasticsearchOperations.delete(product);
       System.out.println(delete);
       return result(delete);
   }

   /**
    * 删除所有文档数据
    */
   @DeleteMapping("deleteAll")
   public Map testDeleteAll() {
       Query query = Query.findAll();
       ByQueryResponse byQueryResponse = elasticsearchOperations.delete(query, Product.class);
       return result(byQueryResponse.getFailures());
   }

   /**
    * 查询所有文档数据
    */
   @GetMapping("queryAll")
   public Map testQueryAll() {
       SearchHits<Product> productSearchHits = elasticsearchOperations.search(Query.findAll(), Product.class);
       System.out.println("总分数: " + productSearchHits.getMaxScore());
       System.out.println("符合条件总数: " + productSearchHits.getTotalHits());
       for (SearchHit<Product> productSearchHit : productSearchHits) {
           System.out.println(JSON.toJSONString(productSearchHit.getContent()));
       }
       return result(productSearchHits.getSearchHits());
   }

   // 组装数据,返回Product对象
   private static Product getProduct(Map<String, Object> param) {
       String id = String.valueOf(param.get("id"));
       String title = String.valueOf(param.get("title"));
       Double price = Double.valueOf(String.valueOf(param.get("price")));
       String description = String.valueOf(param.get("description"));
       String category = String.valueOf(param.get("category"));
       String images = String.valueOf(param.get("images"));
       Product product = new Product(id, title, price, description, category, images);
       return product;
   }

   // 组装数据,返回List<Product>对象
   public List<Product> batchProductList(Map<String, Object> param) {
       if (ObjectUtils.isEmpty(param)) return null;
       Product product = getProduct(param);
       List<Product> list = new ArrayList<>();
       list.add(product);
       for (int i = 0; i < 10; i++) {
           list.add(setProduct(product, i));
       }
       return list;
   }

   // 统一向前台返回Map
   private Map<String, Object> result(Object result) {
       RESULT.clear();
       boolean bool = (result instanceof Boolean) ? (Boolean) result : Objects.nonNull(result);
       RESULT.put("code", bool ? 200 : 500);
       RESULT.put("msg", bool ? "success" : "failed");
       RESULT.put("flag", bool);
       RESULT.put("result", result);
       if (bool && result instanceof Collection) {
           Collection coll = (Collection) result;
           RESULT.put("total", coll.size());
       }
       return RESULT;
   }

   // 组装数据,返回Product对象
   public Product setProduct(Product product, int num) {
       Product pro = new Product();
       pro.setId(product.getId() + num);
       pro.setTitle(product.getTitle() + num);
       pro.setPrice(product.getPrice() + num);
       pro.setDescription(product.getDescription() + num);
       pro.setCategory(product.getCategory());
       pro.setImages(product.getImages() + num);
       return pro;
   }

   // 为空时返回指定数据
   private <T> T isNull(Object obj, Object def) {
       return (T) (ObjectUtils.isEmpty(obj) ? def : obj);
   }
}

测试结果

在这里插入图片描述

3、使用RestHighLevelClient实现对ElasticSearch数据的操作

配置文件和配置类和实体类与上面的案例一致,没有改变

控制器获取参数查询


/**
 * @ApiNote: 使用RestHighLevelClient方式操作ElasticSearch$
 * @Author: 陌路
 * @Date: 2023/4/25 11:31
 * @Tool: Created by IntelliJ IDEA
 */
@RestController
@RequestMapping("/restHighLevelClient/")
public class RestHighLevelClientController {

    @Autowired
    @Qualifier("elasticsearchClient")
    private RestHighLevelClient elasticsearchClient;
    private static final Map<String, Object> RESULT = new HashMap<>(2);

    /**
     * 查询所有
     */
    @GetMapping("matchAll")
    public Map testMatchAll() throws IOException {
        // 1.搜索请求对象
        SearchRequest searchRequest = new SearchRequest("products");
        // 2.指定条件对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 3.配置请求对象中的条件对象
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());  // 查询所有
        searchRequest.source(searchSourceBuilder);
        // 参数1: 搜索的请求对象     参数2: 请求配置对象     返回值: 擦汗寻结果对象
        SearchResponse searchResponse = elasticsearchClient.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println("总条数: " + searchResponse.getHits().getTotalHits().value);
        System.out.println("最大得分: " + searchResponse.getHits().getMaxScore());
        // 获取结果
        SearchHit[] hits = searchResponse.getHits().getHits();
        return result(hits);
    }

    /**
     * 范围查询 range
     * @param minPrice 最小
     * @param maxPrice 最大
     */
    @GetMapping("range")
    public Map testRange(Integer minPrice, Integer maxPrice) throws IOException {
        minPrice = isNull(minPrice, 5);
        maxPrice = isNull(maxPrice, 15);
        return query(QueryBuilders.rangeQuery("price").gt(minPrice).lt(maxPrice));
    }

    /**
     * 根据id查询数据
     * @param ids 多个id数据
     */
    @GetMapping("ids")
    public Map testIds(String[] ids) throws IOException {
        // "*"代表多个字符,"?"代表一个字符
        return query(QueryBuilders.idsQuery().addIds(ids));
    }

    /**
     * 多字段查询 multi_match
     * @param desc 查询词条
     */
    @GetMapping("multiMatch")
    public Map testMultiMatch(String desc) throws IOException {
        // 如果查的字段分词,会先进行分词处理,否则不进行分词处理
        return query(QueryBuilders.multiMatchQuery(desc, "title", "description"));
    }

    /**
     * 数据查询
     * @param queryBuilder 查询条件
     */
    public Map query(QueryBuilder queryBuilder) throws IOException {
        // 1.搜索请求对象
        SearchRequest searchRequest = new SearchRequest("products");
        // 2.指定条件对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 3.配置请求对象中的条件对象
        searchSourceBuilder.query(queryBuilder);  // 关键字
        searchRequest.source(searchSourceBuilder);
        // 参数1: 搜索的请求对象     参数2: 请求配置对象     返回值: 擦汗寻结果对象
        SearchResponse searchResponse = elasticsearchClient.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println("总条数: " + searchResponse.getHits().getTotalHits().value);
        System.out.println("最大得分: " + searchResponse.getHits().getMaxScore());
        // 获取结果
        SearchHit[] hits = searchResponse.getHits().getHits();
        for (SearchHit hit : hits) {
            System.out.println("id: " + hit.getId() + " source: " + hit.getSourceAsString());
        }
        return result(searchResponse.getHits());
    }

    /**
     * 分页查询     from 起始位置   size 分页大小
     * 排序查询     sort
     * 指定字段获取   _source
     * 高亮查询     highlight
     *
     * @throws IOException
     */
    @GetMapping("searchByPage")
    public Map testSearch(String desc, String sortField) throws IOException {
        sortField = isNull(sortField, "price");
        // 1.创建请求索引对象
        SearchRequest searchRequest = new SearchRequest("products");
        // 2.创建搜索条件对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 3.创建高亮对象
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.requireFieldMatch(false)   // 注意: 开启高亮的字段必须可以分词,不然查询结果无效
                .preTags("<span style='color: red;'>")  // 配置高亮包裹前缀
                .postTags("</span>")                    // 配置高亮包裹后缀
                .field("description")                   // 指定高亮字段
                .field("title");                        // 指定高亮字段
        searchSourceBuilder
//                .query(QueryBuilders.termQuery("description", desc))
                .from(0)    // 起始位置
                .size(5)    // 分页大小,默认返回是10条
                .sort(sortField, SortOrder.DESC) // 指定排序字段以及排序方式
                .fetchSource(null, new String[]{"createTime"})  // 参数1: 包含字段数组  参数2: 排除字段数组  注意,当两者结合使用时,只有前者会生效
                .highlighter(highlightBuilder)
        ;
        // 4.为请求对象配置搜素对象
        searchRequest.source(searchSourceBuilder);
        // 5.接收响应对象
        SearchResponse searchResponse = elasticsearchClient.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println("总条数: " + searchResponse.getHits().getTotalHits().value);
        System.out.println("最大得分: " + searchResponse.getHits().getMaxScore());
        // 获取结果
        SearchHit[] hits = searchResponse.getHits().getHits();
        return result(hits);
    }

    /**
     * 基于 term 类型进行聚合,并且基于字段进行分组聚合
     */
    @GetMapping("aggs")
    public Map testAggs() throws IOException {
        // 1.创建请求对象
        SearchRequest searchRequest = new SearchRequest("products");
        // 2.创建查询对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder
                .query(QueryBuilders.matchAllQuery())
                .aggregation(AggregationBuilders.terms("price_group").field("price"))   // 用于设置聚合处理
                .size(0);
        // 3.为请求对象配置查询对象
        searchRequest.source(searchSourceBuilder);
        // 4.接收响应对象
        SearchResponse searchResponse = elasticsearchClient.search(searchRequest, RequestOptions.DEFAULT);
        // 5.处理聚合结果
        Aggregations aggregations = searchResponse.getAggregations();
        // 根据字段类型,转移
        ParsedDoubleTerms price_group = aggregations.get("price_group");
        // 解析桶里的内容
        List<? extends Terms.Bucket> buckets = price_group.getBuckets();
        return result(buckets);
    }

    /**
     * 基于 sum(ParsedSum)、avg(ParsedAvg)、max(ParsedMax)、min(ParsedMin) 函数聚合,
     */
    @GetMapping("aggsFunction")
    public Map testAggsFunction() throws IOException {
        // 1.创建请求对象
        SearchRequest searchRequest = new SearchRequest("products");
        // 2.创建查询对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder
                .query(QueryBuilders.matchAllQuery())
                .aggregation(AggregationBuilders.sum("sum_price").field("price"))   // 用于设置聚合处理,sum、avg、max、min
                .size(0);
        // 3.为请求对象配置查询对象
        searchRequest.source(searchSourceBuilder);
        // 4.接收响应对象
        SearchResponse searchResponse = elasticsearchClient.search(searchRequest, RequestOptions.DEFAULT);
        // 5.处理聚合结果
        Aggregations aggregations = searchResponse.getAggregations();
        // 根据字段类型,转移    ParsedSum、ParsedAvg、ParsedMax、ParsedMin
        ParsedSum sum_price = aggregations.get("sum_price");
        // 解析桶里的内容
        System.out.println(sum_price.getValue());
        return result(aggregations);
    }

    // 统一向前台返回Map
    private Map<String, Object> result(Object result) {
        RESULT.clear();
        boolean bool = (result instanceof Boolean) ? (Boolean) result : Objects.nonNull(result);
        RESULT.put("code", bool ? 200 : 500);
        RESULT.put("msg", bool ? "success" : "failed");
        RESULT.put("flag", bool);
        RESULT.put("result", result);
        if (bool && result instanceof Collection) {
            Collection coll = (Collection) result;
            RESULT.put("total", coll.size());
        }
        return RESULT;
    }

    // 为空时返回指定数据
    private <T> T isNull(Object obj, Object def) {
        return (T) (ObjectUtils.isEmpty(obj) ? def : obj);
    }
}

测试查询结果

在这里插入图片描述

以上为SpringBoot对ElasticSearch的分词、分组、分词高亮、分页、范围、新增、修改操作,以上为全部的代码,代码复制粘贴即可运行测试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/460799.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小红书笔记发布软件 批量上传视频

百收网SEO短视频矩阵发布丨9平台视频发布助手 软件简述&#xff1a;软件仅支持win系统&#xff0c; 软件使用的是网页版模拟协议软件不绑定电脑&#xff0c;任意换机&#xff0c;不限登录账号数量&#xff0c; 软件支持抖音&#xff0c;快手&#xff0c;视频号&#xff0c;西瓜…

P1034 [NOIP2002 提高组] 矩形覆盖

题目描述 在平面上有 &#xfffd;n 个点&#xff0c;每个点用一对整数坐标表示。例如&#xff1a;当 &#xfffd;4n4 时&#xff0c;44 个点的坐标分另为&#xff1a;&#xfffd;1(1,1)p1​(1,1)&#xff0c;&#xfffd;2(2,2)p2​(2,2)&#xff0c;&#xfffd;3(3,6)p3​…

设备树总结

设备树的概念: 设备树&#xff08;Device Tree:DT&#xff09;是用来描述设备信息的一种树形结构。设备树文件在linux内核启动的时候传递到内核被内核解析。设备树中每一个设备节点中的信息构成了一个属性链表&#xff0c;如果驱动想要使用这个设备信息&#xff0c;只需要在这…

UE4架构初识(五)

UE4仿真引擎学习 一、架构基础 1. GameInstance UE提供的方案是一以贯之的&#xff0c;为我们提供了一个GameInstance类。为了受益于UObject的反射创建能力&#xff0c;直接继承于UObject&#xff0c;这样就可以依据一个Class直接动态创建出来具体的GameInstance子类。 UGam…

Pytest接口自动化测试实战演练

结合单元测试框架pytest数据驱动模型allure 目录 api&#xff1a; 存储测试接口conftest.py :设置前置操作目前前置操作&#xff1a;1、获取token并传入headers&#xff0c;2、获取命令行参数给到环境变量,指定运行环境commmon&#xff1a;存储封装的公共方法connect_mysql.p…

C. Magic Ship(二分 + 前缀和)

Problem - C - Codeforces 你是一艘船的船长。最初你站在一个点(x1&#xff0c;y1)上&#xff08;很明显&#xff0c;海上的所有位置都可以用笛卡尔平面描述&#xff09;&#xff0c;你想要前往一个点(x2&#xff0c;y2)。 你知道天气预报——长度为n的字符串s&#xff0c;仅由…

实战详解Docker快速搭建部署ELK

一.安装前须知 以下步骤在 VMware 中的 centos 7 中操作&#xff0c;ip 地址为&#xff1a;192.168.161.128&#xff1b; 注意安装的时候最好统一版本&#xff0c;否则后面会出现许多问题&#xff0c;进官网搜索对应镜像&#xff0c;查看 Tags 标签下的版本&#xff0c;目前我…

记一次死锁问题

最近在做一个需求&#xff0c;碰到了死锁的问题&#xff0c;记录下解决问题的过程 背景 这个需求要改动一个接口&#xff0c;我这边称为A接口&#xff0c;原先的逻辑是A接口内部会调用c方法&#xff0c;c方法是一个dubbo方法&#xff0c; 现在需要再A接口里添加调用B方法&…

springcloud之Feign、ribbon设置超时时间和重试机制的总结

目录标题 超时时间ribbon和Feignribbon和Feign默认超时时间关于ribbon和Feign超时时间配置说明 关于hystrix默认超时时间与配置说明 ribbon的重试机制重试的次数hystrix超时时间举个例子 超时时间 feign/ribbon对应的是请求的时间 hystrix对应的是断路器的时间 一般情况下 都是…

【Linux】2. 常见指令

1. 操作系统的定义 在真正了解Linux操作系统之前&#xff0c;我们需要初步明确什么是操作系统 Linux下的基本指令 指令的作用是什么&#xff0c;其实就是相当于Windows的基本操作&#xff0c;Linux操作系统是以命令行显示的&#xff0c;而Windows则是以图形化界面的方式展现…

图像融合方向:《Deep Image Blending》论文理解

《Deep Image Blending》论文理解 论文&#xff1a;《Deep Image Blending》WACV 2020 链接&#xff1a;Deep Image Blending 本文目录 《Deep Image Blending》论文理解论文创新点具体实现思路文中使用的基准方法文章内容解析使用模型整体架构两阶段算法详情第1阶段第2阶段 损…

一款高效、可靠的自动化测试平台,提升效率、降低测试成本

一、开源项目简介 扬帆测试平台是一款高效、可靠的自动化测试平台&#xff0c;旨在帮助团队提升测试效率、降低测试成本。该平台包括用例管理、定时任务、执行记录等功能模块&#xff0c;支持多种类型的测试用例&#xff0c;目前支持API(http和grpc协议)、性能&#xff0c;并且…

轻量级服务器nginx:负载均衡

负载均衡就是让每个设备&#xff0c;以同样的概率&#xff0c;处理用户对于服务器的任务请求&#xff0c;默认采用的负载调度策略就是轮流询问&#xff0c;Nginx作为反向代理服务器安装在服务端&#xff0c;Nginx的功能就是把请求转发给后面的应用服务器. 这里写目录标题 一 负…

差分优化算法——DE

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; 目录 一、DE1.步骤2.特点 二、DE Optimiza1.函数最小值问题2.差分进化算法求解2.Java 实现与结果绘图 一、DE 差分进化算法是一种基于群体智能的优化算法&#xff0c;由Storn和Price于1995年提出&#xff0c;最早用…

vue3+ts开发微信小程序----使用FontAwesome图标的步骤(只适用于面性图标)

vue3ts开发微信小程序----使用FontAwesome图标的步骤&#xff08;只适用于面性图标&#xff09; 因为用的vue3ts 但是对于npm引进FontAwesome来说&#xff0c;好像对于小程序不支持&#xff0c;所以用了引入文件的方式。 下载FontAwesome字体&#xff0c;我用的是5版本的。[官方…

从初识RabbitMQ到安装了解

一、同步和异步通讯 微服务间通讯有同步和异步两种方式&#xff1a; 同步通讯&#xff1a;就像打电话&#xff0c;需要实时响应。 异步通讯&#xff1a;就像发邮件&#xff0c;不需要马上回复。 两种方式各有优劣&#xff0c;打电话可以立即得到响应&#xff0c;但是你却不…

记 SAM React Demo 转 Vue 遇到的一些问题

前言 SegmentAnything Model (SAM) 是 Meta 开源的分割万物 AI 模型&#xff0c;因笔者主要使用 Vue&#xff0c;因此对官方 Demo 进行了工程迁移工作&#xff0c;这里记录了迁移过程遇到的一些问题。 没有使用多线程加速 官方的 React Demo 项目使用ort-wasm-simd-threaded…

态路小课堂丨浅谈IDC数据中心综合布线互联

在数据中心发展过程中&#xff0c;服务器、光模块等设备更新周期短&#xff0c;迭代快。但是&#xff0c;对于IDC数据中心综合布线系统来说&#xff0c;其使用周期一般都比较长。因此&#xff0c;为了能够匹配IDC数据中心的发展&#xff0c;关于综合布线的设计尤为重要。 目前&…

【vue】elementUI中el-table拖动滚动条的时候固定某一列

文章目录 前言&#xff1a;需求 前言&#xff1a; 写项目的时候有一个需求&#xff0c;就是当el-table的滚动条滑动的时候&#xff0c;可见区域如果没有该列则固定到左侧&#xff0c;由elementUi官方网站可知el-table固定一列的代码如下: fixed为主要的标识 头部固定设置的是t…

leetcode 2336. Smallest Number in Infinite Set(有限集中的最小数字)

实现一个SmallestInfiniteSet类(后面用set简称)&#xff0c;满足以下功能&#xff1a; 初始化时&#xff0c;set含有所有的正整数。 pop函数返回set中最小的整数。 add函数在set中添加一个整数。 思路&#xff1a; set具有以下的功能&#xff1a; 可以取出最小的数字。 可以查…