商城:整合ElasticSearch
创建es检索服务模块
1.新建module gulimall-search
2.pom导入依赖
<!--引入es的JAVA REST Client 高阶依赖-->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.4.2</version>
</dependency>
这里注意springboot指定的elasticsearch版本肯本可能不一样,需要自己指定一下!
<properties>
<elasticsearch.version>7.4.2</elasticsearch.version>
</properties>
3.新建配置类 ElasticsearchConfig
目前暂时用不到RequestOptions
,所以在配置类中将一些配置先注释掉,等需要用到再进行配置。
ElasticsearchConfig
/**
* 1. 导入依赖
* 2. 编写配置,给容器中注入一个RestHighLevelClient
* 3. 参照API文档操作
*/
@Configuration
public class GulimallElasticSearchConfig {
/**
* 配置请求选项
* 参考:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-low-usage-requests.html#java-rest-low-usage-request-options
*/
public static final RequestOptions COMMON_OPTIONS;
static {
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
// builder.addHeader("Authorization", "Bearer " + TOKEN);
// builder.setHttpAsyncResponseConsumerFactory(
// new HttpAsyncResponseConsumerFactory
// .HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024));
COMMON_OPTIONS = builder.build();
}
@Bean
public RestHighLevelClient esRestClient() {
// 集群模式下,需要指明每个es的ip跟端口号,有几个集群就new 几个HttpHost
// RestHighLevelClient client = new RestHighLevelClient(
// RestClient.builder(new HttpHost("192.168.190.135", 9200, "http"))
// );
// 把上面的拆分一下
RestClientBuilder builder = null;
builder = RestClient.builder(new HttpHost("192.168.190.135", 9200, "http"));
RestHighLevelClient client = new RestHighLevelClient(builder);
return client;
}
}
如果无法启动,在主启动类上排除数据库配置类:@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
测试
测试均在GulimallSearchApplicationTests类中完成
测试配置类注入
//@RunWith(SpringRunner.class)
@SpringBootTest
public class GulimallSearchApplicationTests {
@Autowired
private RestHighLevelClient restHighLevelClient;
@Test
public void contextLoads() {
System.out.println(restHighLevelClient);
}
}
打印: org.elasticsearch.client.RestHighLevelClient@3686389
测试Index API (存储数据)
提供文档源(要存储的数据)有很多方式:
- String字符串
- Map
- XContentBuilder 对象
- KV 键值对
- 自定义类型对象转JSON字符串 (常用)
文档源设置完成后,便需要执行提交到es,执行分为同步与异步执行,具体可以参考文档。
json测试插入
@Test
public void indexData() throws IOException {
// 创建IndexRequest,并指定index名(在哪个索引下面存储数据)
IndexRequest indexRequest = new IndexRequest("users");
indexRequest.id("1"); // 设置id,必须为字符串的形式,不设置会自动生成
// source方法用于设置文档数据,数据可以有多种格式
// 1.json字符串 2.Map 3.XContentBuilder 4.KV键值对
// kv键值对方式传输
//indexRequest.source("username", "zhangsan", "age", 18, "gender", "男");
// 将自定义对象转为json字符串传输
User user = new User();
user.setUserName("zhangsan");
user.setGender("男");
user.setAge(18);
// 把对象转为json字符串
String jsonString = JSON.toJSONString(user);// 需要导入com.alibaba.fastjson依赖
indexRequest.source(jsonString, XContentType.JSON); // 这里需要指明内容类型
// 执行保存操作,执行分为同步与异步的方式,这里使用同步执行
// 只要是网络操作,必然会考虑到异常,index方法会抛出IOException
IndexResponse indexResponse = client.index(indexRequest, ElasticsearchConfig.COMMON_OPTIONS);
// 提取有用的响应数据
System.out.println(indexResponse);
}
@Data
class User {
private String userName;
private String gender;
private Integer age;
}
执行之前 GET users/_search 查询无数据,执行之后查询有数据!
复杂检索测试
复杂检索测试代码
@Test
public void searchData() throws IOException {
// 1.创建检索请求
SearchRequest searchRequest = new SearchRequest();
// SearchRequest searchRequest = new SearchRequest("bank"); // 也可以创建的时候直接指定index
searchRequest.indices("bank"); // 指定从哪个index检索
// 指定DSL,检索条件
// searchSourceBuilder 封装了全部检索条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 1.1 构造检索条件
// searchSourceBuilder.query();
// searchSourceBuilder.from();
// searchSourceBuilder.size();
// searchSourceBuilder.aggregation();
// 搜索 address 中包含 mill 的所有人的年龄分布以及平均年龄
searchSourceBuilder.query(QueryBuilders.matchQuery("address", "mill"));
// 1.2 按照年龄的值分布进行聚集
TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg").field("age").size(10);
searchSourceBuilder.aggregation(ageAgg);
// 1.3 计算match条件得到结果的平均薪资
AvgAggregationBuilder balanceAvg = AggregationBuilders.avg("balanceAvg").field("balance");
searchSourceBuilder.aggregation(balanceAvg);
System.out.println("检索条件" + searchSourceBuilder.toString());
searchRequest.source(searchSourceBuilder);
// 2.执行检索 同样分为异步与同步
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, GulimallElasticSearchConfig.COMMON_OPTIONS);
// 3.分析检索结果 searchResponse
System.out.println(searchResponse.toString());
// JSON.parseObject(searchResponse.toString(), Map.class);
// 3.1 获取所有查到的文档
SearchHits hits = searchResponse.getHits(); // 这是外面最大的hits,里面有个hits数组存储的命中文档
SearchHit[] searchHits = hits.getHits();
for (SearchHit searchHit : searchHits) {
/**
* "_index" : "bank",
* "_type" : "account",
* "_id" : "970",
* "_score" : 5.4032025,
* "_source"
*/
// searchHit.getIndex();
String string = searchHit.getSourceAsString(); // 结果映射成JSON字符串
Account account = JSON.parseObject(string, Account.class); // 通过JSON.parseObject 把JSON字符串转为对象,Account如果是内部类必须是static的
System.out.println("account:" + account);
}
// 3.2 获取这次检索到的分析信息
Aggregations aggregations = searchResponse.getAggregations(); // 获取所有聚合结果
// for (Aggregation aggregation : aggregations.asList()) {
// System.out.println("当前聚合名称" + aggregation.getName());
// }
Terms ageAgg1 = aggregations.get("ageAgg");
for (Terms.Bucket bucket : ageAgg1.getBuckets()) {
System.out.println("年龄:" + bucket.getKeyAsString() + "==>" + bucket.getDocCount());
}
Avg balanceAvg1 = aggregations.get("balanceAvg");
System.out.println(balanceAvg1.getValue());
}
@Data
@ToString
static class Account {
private int account_number;
private int balance;
private String firstname;
private String lastname;
private int age;
private String gender;
private String address;
private String employer;
private String email;
private String city;
private String state;
}
阅读剩余
版权声明:
作者:Tin
链接:http://www.tinstu.com/2616.html
文章版权归作者所有,未经允许请勿转载。
THE END