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);
}
}