集成Springboot
导入pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
ES 的核心概念
索引
一个索引就是一个拥有几分相似特征的文档集合,比如说,你可以有一个商品数据的索引,一个订单数据索引,还有一个用户数据的索引,一个索引有一个名字来标识(ps:必须是小写字母全部)并且当我们要对这个索引中的文档进行索引,搜索,更新和删除的时候都要用这个名字。
映射
映射是定义一个文档和它所在包含的字段如何被储存和索引的过程
,在默认配置下 ES 可以根据插入的数据自动创建mapping 也可以手动创建mapping mapping 中主要包括字段名,字段类型等
文档
文档是索引中存储的一条条数据,一条文档是一个可被索引的最小单元,ES 中的文档采用了轻量级的JSON 格式数据来表示。
使用 RestHighLevelClient
创建elasticsearchConfig
@Configuration
public class SpringbootConfig {
@Bean
public RestHighLevelClient restHighLevelClient() {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
return client;
}
}
索引操作 (CRUD)
@Autowired
@Qualifier("restHighLevelClient")
RestHighLevelClient client;
// 创建索引
@Test
void CreateIndex() throws IOException {
CreateIndexRequest request = new CreateIndexRequest("fengjioajaio");
CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
System.out.println(response);
}
// 获取索引
@Test
void GetIndex() throws IOException {
GetIndexRequest request = new GetIndexRequest("fengjioajaio");
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(exists);
}
// 删除索引
@Test
void DeleteIndex() throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest("fengjioajaio");
AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
System.out.println(delete);
}
文档操作 (CRUD)
// 添加文档
@Test
void AddDoc() throws IOException {
User user = new User("娇娇", "123456", "^(* ̄(oo) ̄)^");
// 创建要添加的索引
IndexRequest request = new IndexRequest("fengjioajaio");
// 添加 id 等
request.id("1").timeout("1s").timeout(TimeValue.timeValueSeconds(1)).source(JSON.toJSONString(user), XContentType.JSON);
// 发送客户端
IndexResponse index = client.index(request, RequestOptions.DEFAULT);
System.out.println(index.status());
System.out.println(index.toString());
}
// 获取文档
@Test
void GetDoc() throws IOException {
GetRequest request = new GetRequest("fengjioajaio","1");
GetResponse response = client.get(request, RequestOptions.DEFAULT);
System.out.println(response.getSourceAsString()); // 打印文档的内容
System.out.println(response);
}
// 更新文档
@Test
void UpdateDoc() throws IOException {
UpdateRequest request = new UpdateRequest("fengjioajaio", "1");
User user = new User("我是美女", "23444", "fjrkfkggre");
request.id("1").timeout("1s").doc(JSON.toJSONString(user),XContentType.JSON);
UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
System.out.println(update);
System.out.println(request);
}
// 删除文档
@Test
void DeleteDoc() throws IOException {
DeleteRequest request = new DeleteRequest("fengjioajaio");
request.id("1");
DeleteResponse delete = client.delete(request, RequestOptions.DEFAULT);
System.out.println(delete);
}
// 批量插入数据
@Test
void BuckAdd(List<?> list,String IndexName) throws IOException {
BulkRequest request = new BulkRequest();
list.forEach(s -> {
request.timeout("10s").add(new IndexRequest(IndexName).source(JSON.toJSONString(s),XContentType.JSON));
});
BulkResponse bulk = client.bulk(request, RequestOptions.DEFAULT);
System.out.println("bulk = " + bulk);
}
文档查询 花式查询
查询全部
@Test
// 查询全部
public void queryAll() throws IOException {
// 这里可以添加多个索引的名字 indixes 是加了s 的是可以添加多个 索引给他 查询的请求
SearchRequest request = new SearchRequest(INDEX_NAME);
// 创建构造器
SearchSourceBuilder builder = new SearchSourceBuilder();
// 添加搜索的条件
builder.query(QueryBuilders.matchAllQuery());
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 总条数
System.out.println("总条数"+response.getHits().getTotalHits().value);
// 最大分数
System.out.println("最大分数"+response.getHits().getMaxScore());
// 查询时间
System.out.println("查询时间"+response.getTook());
// 拿到我们的数据
SearchHit[] hits = response.getHits().getHits();
Arrays.stream(hits).forEach(s->{
System.out.println("id 是" +s.getId());
// 具体数据
System.out.println("具体数据"+s.getSourceAsString());
});
}
这里需要注意一下 ES 在不设置分页的时候默认是出来10条数据
要是想查看全部数据的话 可以 设置分页 这样就可以显示多个数据了。
关键字查询
SearchRequest request = new SearchRequest(INDEX_NAME);
// 创建构造器
SearchSourceBuilder builder = new SearchSourceBuilder();
// 添加条件 adress 是你的字段名 后面的是你要查询什么
builder.query(QueryBuilders.termQuery("address","安"));
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 总条数
System.out.println("总条数"+response.getHits().getTotalHits().value);
// 最大分数
System.out.println("最大分数"+response.getHits().getMaxScore());
// 查询时间
System.out.println("查询时间"+response.getTook());
// 拿到我们的数据
SearchHit[] hits = response.getHits().getHits();
Arrays.stream(hits).forEach(s->{
System.out.println("id 是" +s.getId());
// 具体数据
System.out.println("具体数据"+s.getSourceAsString());
});
这里代码有点冗余,我把关键的代码抽离出来了
// 抽离出来的查询的方法
public void query (QueryBuilder queryBuilder) throws IOException{
// 创建 请求
SearchRequest request = new SearchRequest(INDEX_NAME);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(queryBuilder);
request.source(builder);
// 发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 总条数
System.out.println("总条数"+response.getHits().getTotalHits().value);
// 最大分数
System.out.println("最大分数"+response.getHits().getMaxScore());
// 查询时间
System.out.println("查询时间"+response.getTook());
// 拿到我们的数据
SearchHit[] hits = response.getHits().getHits();
Arrays.stream(hits).forEach(s->{
System.out.println("id 是" +s.getId());
// 具体数据
System.out.println("具体数据"+s.getSourceAsString());
});
}
尝试 代码少了很多冗余的
// 关键词查询
@Test
public void queryLike() throws IOException {
query(QueryBuilders.termQuery("address","南"));
}
范围查询
// range 查询
@Test
public void queryRange() throws IOException{
query(QueryBuilders.rangeQuery("id").gt(1).lte(20));
}
前缀查询
// 前缀查询
@Test
public void queryPrefix() throws IOException {
query(QueryBuilders.prefixQuery("address","贵州省"));
}
通配符查询
@Test
public void queryDemo() throws IOException {
// 通配符查询 ? 表示一个字符 * 任意多个字符
query(QueryBuilders.wildcardQuery("address","贵州省*"));
}
ids 多个指定的 id查询
@Test
public void queryDemo() throws IOException {
// ids 多个指定 id 查询
query(QueryBuilders.idsQuery().addIds("1"));
}
多字段查询
@Test
public void queryDemo() throws IOException {
// multi_match 多字段查询
query(QueryBuilders.multiMatchQuery("贵州省","address","title"));
}
模糊查询
@Test
public void queryDemo() throws IOException {
query(QueryBuilders.fuzzyQuery("address","贵州省"));
}
这里要注意
- 搜索关键词长度为2 不允许存在模糊
- 搜索关键词为3-5 允许一次模糊
- 搜索关键词长度大于5允许最大的模糊
布尔查询
@Test
public void queryDemo() throws IOException {
query(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("address","贵州省")).must(QueryBuilders.idsQuery().addIds("1")));
}
- bool 关键字用来组合多个条件实现复杂查询
- must :相当于 && 同时成立
- should 相当于 || 成立一个就行
- must_not :相当于!不能满足任何一个
默认字段分词查询
@Test
public void queryDemo() throws IOException {
query(QueryBuilders.queryStringQuery("address").queryName("贵州省"));
}
返回指定字段
@Test
public void querySize() throws IOException {
SearchRequest request = new SearchRequest(INDEX_NAME);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery());
//1, 包含字段的数组 2 排除字段数组
builder.fetchSource(new String[]{"address"},new String[]{});
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHit[] hits = response.getHits().getHits();
Arrays.stream(hits).forEach(s->{
System.out.println(s.getSourceAsString());
});
}
分页查询
@Test
public void querySize() throws IOException {
SearchRequest request = new SearchRequest(INDEX_NAME);
SearchSourceBuilder builder = new SearchSourceBuilder();
// 每页显示的条数
builder.size(2);
// 起始字段
builder.from(0);
builder.query(QueryBuilders.matchAllQuery());
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHit[] hits = response.getHits().getHits();
Arrays.stream(hits).forEach(s->{
System.out.println(s.getSourceAsString());
});
}
排序
@Test
public void querySize() throws IOException {
SearchRequest request = new SearchRequest(INDEX_NAME);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery());
// 第一个字段是你要通过那个字段来进行排序 第二个参数 你要如何排序
builder.sort("id", SortOrder.DESC);
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHit[] hits = response.getHits().getHits();
Arrays.stream(hits).forEach(s->{
System.out.println(s.getSourceAsString());
});
}
高亮查询
@Test
public void querySize() throws IOException {
SearchRequest request = new SearchRequest(INDEX_NAME);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.termQuery("贵州","address"));
// 创建高亮器
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.requireFieldMatch(false).field("address");
builder.highlighter(highlightBuilder);
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHit[] hits = response.getHits().getHits();
Arrays.stream(hits).forEach(s->{
Map<String, HighlightField> map = s.getHighlightFields();
if (map.containsKey("address")) {
System.out.println("map.get(\"address\").fragments()[0] = " + map.get("address").fragments()[0]);
}
});
}
过滤查询
过滤查询
@Test
// 查询全部
public void queryAll() throws IOException {
// 这里可以添加多个索引的名字 indixes 是加了s 的是可以添加多个 索引给他 查询的请求
SearchRequest request = new SearchRequest(INDEX_NAME);
// 创建构造器
SearchSourceBuilder builder = new SearchSourceBuilder();
// 添加搜索的条件 如果同时使用过滤跟query 的话优先是执行的 过滤的
builder.query(QueryBuilders.matchAllQuery()).postFilter(QueryBuilders.termQuery("address","贵州省"));
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 总条数
System.out.println("总条数"+response.getHits().getTotalHits().value);
// 最大分数
System.out.println("最大分数"+response.getHits().getMaxScore());
// 查询时间
System.out.println("查询时间"+response.getTook());
// 拿到我们的数据
SearchHit[] hits = response.getHits().getHits();
Arrays.stream(hits).forEach(s->{
System.out.println("id 是" +s.getId());
// 具体数据
System.out.println("具体数据"+s.getSourceAsString());
});
}
聚合查询
聚合是ES除搜索功能外提供的针对es 数据做统计分析的功能。聚合有助于根据搜索查询提供聚合数据。聚合查询是数据库中重要的功能特效,ES 作为搜索引擎兼数据库 同样提供了强大的聚合分析能力 它基于查询条件来对数据进行分桶,计算的方法 有点类似于SQL 中的 group by 再加一些函数方法的操作。
根据某个字段分组
@Test
public void queryAggs() throws IOException {
SearchRequest request = new SearchRequest(INDEX_NAME);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchAllQuery())
.aggregation(AggregationBuilders.terms("contractTerm_group").field("contractTerm")) // 设置聚合操作
.size(0)
; // 查询条件
request.source(searchSourceBuilder);
// 客户端发送消息
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
Aggregations aggregations = response.getAggregations();
ParsedDoubleTerms aggregation = aggregations.get("contractTerm_group");
List<? extends Terms.Bucket> list = aggregation.getBuckets();
list.stream().forEach(s->{
System.out.println(s.getKey());
System.out.println(s.getDocCount());
});
}
求最大值
@Test
public void queryMax() throws IOException{
SearchRequest request = new SearchRequest(INDEX_NAME);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery())
.aggregation(AggregationBuilders.max("contractTerm_max").field("contractTerm"));
request.source(builder);
// 客户端发送消息
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 打印数据
Aggregations aggregations = response.getAggregations();
ParsedMax aggregation = aggregations.get("contractTerm_max");
double value = aggregation.getValue();
System.out.println(
value
);
}
最小值
@Test
public void queryMax() throws IOException{
SearchRequest request = new SearchRequest(INDEX_NAME);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery())
.aggregation(AggregationBuilders.min("contractTerm_min").field("contractTerm"));
request.source(builder);
// 客户端发送消息
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 打印数据
Aggregations aggregations = response.getAggregations();
ParsedMin aggregation = aggregations.get("contractTerm_min");
double value = aggregation.getValue();
System.out.println(
value
);
}
平均值
// 求平均值
@Test
public void queryAvg() throws IOException {
SearchRequest request = new SearchRequest(INDEX_NAME);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery())
.aggregation(AggregationBuilders.avg("contractTerm_avg").field("contractTerm"))
;
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
Aggregations aggregations = response.getAggregations();
ParsedAvg contractTerm = aggregations.get("contractTerm_avg");
System.out.println(contractTerm.getValue());
}