配置客户端org.springframework.boot spring-boot-starter-data-elasticsearch
@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {
@Override
@Bean
public RestHighLevelClient elasticsearchClient() {
final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo("172.16.91.10:9200")
.build();
return RestClients.create(clientConfiguration).rest();
}
}
SpringBoot提供了两种操作ES的客户端
-
- RestHighLevelClient 推荐
- 特点: 始终使用面向对象方式操作 ES
- 索引: 用来存放相似文档集合
- 映射: 用来决定放入文档的每个字段以什么样方式录入到 ES 中 字段类型 分词器…
- 文档: 可以被索引最小单元 json 数据格式
- @Document(indexName=“products”, createIndex=true) 用在类上,表示为一个ES中的文档
- indexName属性:创建索引的名称
- createIndex属性:是否创建索引
- @Id 标记在属性上,将对象的 id 字段映射成文档中的 _id
- @Field(type=FieldTpye.keyword) :表示索引中字段的类型
- type:指定字段类型
@Document(indexName = "product", createIndex = true)
public class Product {
@Id
private Integer id;
@Field(type = FieldType.Keyword)
private String title;
@Field(type = FieldType.Float)
private Double price;
@Field(type = FieldType.Text)
private String description;
//get set ...
}
基本操作
public class ElasticSearchOptionsTest extends ElasticsearchApplicationTests{
private ElasticsearchOperations elasticsearchOperations;
@Autowired
public ElasticSearchOptionsTest(ElasticsearchOperations elasticsearchOperations){
this.elasticsearchOperations=elasticsearchOperations;
}
@Test
public void testIndex(){
Product product=new Product();
product.setId(1);
product.setTitle("小浣熊干脆面");
product.setPrice(5.5);
product.setDescription("小浣熊干脆面真好吃");
elasticsearchOperations.save(product);
}
@Test
public void queryIndex(){
Product product = elasticsearchOperations.get("1", Product.class);
System.out.println(product);
}
@Test
public void queryAllIndex(){
SearchHits search = elasticsearchOperations.search(Query.findAll(), Product.class);
System.out.println("总分数: "+search.getMaxScore());
System.out.println("符合条件的条数: "+search.getTotalHits());
for (SearchHit searchHit : search) {
System.out.println(searchHit.getContent());
}
}
@Test
public void testDelete(){
//根据Id删除
elasticsearchOperations.delete("1",Product.class);
//删除所有
elasticsearchOperations.delete(Query.findAll(),Product.class);
}
}
RestHighLevelClient
索引操作
创建索引及映射
@Test
public void createIndex() throws IOException {
//创建索引请求,指定索引名
CreateIndexRequest createIndexRequest = new CreateIndexRequest("product");
//设置索引映射,参数1:json格式的映射结构 参数2:指定格式的类型(json)
createIndexRequest.mapping("{n" +
" "properties": {n" +
" "title":{n" +
" "type": "keyword"n" +
" },n" +
" "price":{n" +
" "type": "double"n" +
" },n" +
" "create_at":{n" +
" "type": "date"n" +
" },n" +
" "description":{n" +
" "type": "text"n" +
" }n" +
" }n" +
" }", XContentType.JSON);
//参数1:创建索引请求 ,参数2:索引请求的配置对象,一般直接用默认的
//返回对象包含的索引的创建状态
CreateIndexResponse response = elasticsearchClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
//Acknowledged属性表示了索引是否创建成功
System.out.println(response.isAcknowledged());
}
删除索引
@Test
public void testDeleteIndex() throws IOException {
//返回操作结果
AcknowledgedResponse response = elasticsearchClient.indices().delete(new DeleteIndexRequest("product"), RequestOptions.DEFAULT);
System.out.println("删除结果:"+response.isAcknowledged());
}
文档操作 创建文档
@Test
public void createDoc() throws IOException {
//创建请求索引对象,需要传入索引的名称
IndexRequest indexRequest = new IndexRequest("product");
//可指定id,不指定就UUID,一般传入 json格式的文档
indexRequest.id("1").source("{n" +
" "title":"红烧牛肉面",n" +
" "price":"5.5",n" +
" "create_at":"2022-04-13",n" +
" "description":"红烧牛肉面真难吃"n" +
"}", XContentType.JSON);
//参数1: 索引的请求对象 ,参数2:请求配置对象
IndexResponse response = elasticsearchClient.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(response.status());
}
更新文档
@Test
public void updateDoc() throws IOException {
//参数1:索引名,参数2:文档id
UpdateRequest updateRequest = new UpdateRequest("product","1");
updateRequest.doc("{n" +
" "description":"新:好饿想吃"n" +
" }",XContentType.JSON);
UpdateResponse response = elasticsearchClient.update(updateRequest, RequestOptions.DEFAULT);
System.out.println(response.status());
}
删除文档
@Test
public void deleteDoc() throws IOException{
//参数1:索引名,参数2:id值
DeleteRequest deleteRequest = new DeleteRequest("product","1");
DeleteResponse response = elasticsearchClient.delete(deleteRequest, RequestOptions.DEFAULT);
System.out.println(response.status());
}
查询文档
@Test
public void queryDoc() throws IOException {
GetRequest getRequest = new GetRequest("product","1");
GetResponse response = elasticsearchClient.get(getRequest, RequestOptions.DEFAULT);
System.out.println("ID:"+response.getId());
System.out.println("数据:"+response.getSourceAsString());
}
高级查询
查询所有
@Test
public void queryAll() throws IOException {
//指定搜索的索引
SearchRequest searchRequest = new SearchRequest("product");
//指定查询条件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//查询所有
sourceBuilder.query(QueryBuilders.matchAllQuery());
searchRequest.source(sourceBuilder);
//参数1 :搜索的请求对象 参数2:请求配置对象
SearchResponse response = elasticsearchClient.search(searchRequest,RequestOptions.DEFAULT);
System.out.println("总记录数:"+response.getHits().getTotalHits().value);
System.out.println("最大得分:"+response.getHits().getMaxScore());
//获取结果
SearchHit[] hits = response.getHits().getHits();
for (SearchHit hit : hits) {
System.out.println("Id:"+hit.getId());
System.out.println("source:"+hit.getSourceAsString());
}
}
关键词查询
@Test
public void termQuery() throws IOException {
//指定搜索的索引
SearchRequest searchRequest = new SearchRequest("product");
//指定查询条件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.termQuery("description","吃"));
searchRequest.source(sourceBuilder);
SearchResponse response = elasticsearchClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("符合条件的数量:"+response.getHits().getTotalHits().value);;
System.out.println("获得文档最大分数:"+response.getHits().getMaxScore());;
SearchHit[] hits = response.getHits().getHits();
for (SearchHit hit : hits) {
System.out.println("id:"+hit.getId()+" source:"+hit.getSourceAsString());;
}
}
封装高级查询
public void queryBasic(QueryBuilder queryBuilder) throws IOException {
//指定搜索的索引
SearchRequest searchRequest = new SearchRequest("product");
//指定查询条件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(queryBuilder);
searchRequest.source(sourceBuilder);
SearchResponse response = elasticsearchClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("符合条件的数量:"+response.getHits().getTotalHits().value);;
System.out.println("获得文档最大分数:"+response.getHits().getMaxScore());;
SearchHit[] hits = response.getHits().getHits();
for (SearchHit hit : hits) {
System.out.println("id:"+hit.getId()+" source:"+hit.getSourceAsString());;
}
}
@Test
public void queryTest() throws IOException {
//1.term 关键词查询
queryBasic(QueryBuilders.termQuery("description","吃"));
//2.range 范围查询
queryBasic(QueryBuilders.rangeQuery("price").gt(0).lte(10));
//3.prefix 前缀查询
queryBasic(QueryBuilders.prefixQuery("description","红烧牛肉面"));
//4.wildcard 通配符查询 ?表示一个字符 *表示任意个字符
queryBasic(QueryBuilders.wildcardQuery("title","红烧*"));
//5.ids 多个指定id查询
queryBasic(QueryBuilders.idsQuery().addIds("1").addIds("2"));
//6.multi_math 多字段查询
queryBasic(QueryBuilders.multiMatchQuery("红烧","title","description"));
}
综合查询
@SneakyThrows
@Test
public void queryLimit() throws IOException {
SearchRequest searchRequest = new SearchRequest("product");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//创建高亮器
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.requireFieldMatch(false).field("description").preTags("").postTags("");
searchSourceBuilder.query(QueryBuilders.termQuery("description","面"))
.from(0) //起始位置 (page-1)*size
.size(1) //每页的数量
.sort("price", SortOrder.DESC) // 1.排序的字段 2.排序的方式
.fetchSource(new String[]{}, new String[]{"create_at"}) // 1.包含的字段 2.想要排除的字段
.highlighter(highlightBuilder); //高亮查询
searchRequest.source(searchSourceBuilder);
SearchResponse response = elasticsearchClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("符合条件的数量:" + response.getHits().getTotalHits().value);
System.out.println("获得文档最大分数:" + response.getHits().getMaxScore());
SearchHit[] hits = response.getHits().getHits();
for (SearchHit hit : hits) {
System.out.println("id:" + hit.getId() + " source:" + hit.getSourceAsString());
Map highlightFields = hit.getHighlightFields();
if (highlightFields.containsKey("description")) {
System.out.println("description高亮结果:" + highlightFields.get("description").fragments()[0]);
}
}
}
基于对象操作
Java类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Snacks {
private Integer id;
private String title;
private Double price;
private String description;
}
测试
@Test
public void createIndex() throws IOException {
Snacks snacks = new Snacks();
snacks.setId(1);
snacks.setTitle("卫龙辣条");
snacks.setPrice(0.5);
snacks.setDescription("辣条真好吃");
IndexRequest indexRequest = new IndexRequest("snacks");
indexRequest.id(snacks.getId().toString())
//将对象转化为Json
.source(new ObjectMapper().writeValueAsString(snacks), XContentType.JSON);
IndexResponse response = elasticsearchClient.index(indexRequest, RequestOptions.DEFAULT);
System.out.println("创建结果:"+response.status());
}
@Test
public void queryTest() throws IOException {
SearchRequest searchRequest = new SearchRequest("snacks");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.requireFieldMatch(false).field("description").preTags("").postTags("");
sourceBuilder.query(QueryBuilders.termQuery("description","好吃"))
.highlighter(highlightBuilder);
searchRequest.source(sourceBuilder);
SearchResponse response = elasticsearchClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHit[] hits = response.getHits().getHits();
List list=new ArrayList<>();
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
//将json转换为对象
Snacks snacks = new ObjectMapper().readValue(hit.getSourceAsString(), Snacks.class);
//处理高亮
Map highlightFields = hit.getHighlightFields();
if (highlightFields.containsKey("description")){
snacks.setDescription(highlightFields.get("description").fragments()[0].toString());
}
list.add(snacks);
}
for (Snacks snacks : list) {
System.out.println(snacks);
}
}



