一、概述
ElasticSearch,简称为ES, ES是一个开源的高扩展的分布式全文搜索引擎。它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。
物理设计:
ElasticSearch 在后台把每个索引划分成多个分片,每份分片可以在集群中的不同服务器间迁移。
逻辑设计:
一个索引类型中,包含多个文档,比如说文档1,文档2,文档3。当我们索引一篇文档时,可以通过这样的一个顺序找到它: 索引 -▷ 类型 -▷ 文档ID ,通过这个组合我们就能索引到某个具体的文档。
二、环境搭建
下载安装elasticsearch-6.8.13、es-head-chrome插件。
下载ES相关插件,将插件放置plugins目录下:
三、ES启动
启动命令:elasticsearch.bat
若能成功访问 http://loaclhost:9200,则启动成功
可通过 es-head-chrome插件查看ES后台:
启动kibana:
访问:http://localhost:5601
在开发工具中,可执行Rest命令
四、Springboot项目搭建
创建Springboot项目:
五、添加ES依赖
设置ES版本:
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>6.8.13</elasticsearch.version>
</properties>
导入ES依赖,JSON依赖:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</dependency>
六、编写配置类
@Configuration
public class config {
@Bean
public RestHighLevelClient restHighLevelClient() {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("127.0.0.1", 9200, "http")));
return client;
}
}
七、创建索引
@Test
void testCreateIndex() throws IOException {
HttpHost host = HttpHost.create("http://localhost:9200");
RestClientBuilder builder = RestClient.builder(host);
client = new RestHighLevelClient(builder);
CreateIndexRequest request = new CreateIndexRequest("user");
client.indices().create(request, RequestOptions.DEFAULT);
client.close();
}
八、增删改操作
1、基本Rest命令说明(增、删、改、查命令):
menthod | ur地址 | 描述 |
---|---|---|
PUT | localhost:9200/索引名称/类型名称/文档id | 创建文档(指定文档id) |
POST | localhost:9200/索引名称/类型名称 | 创建文档(随机文档id) |
POST | localhost:9200/索引名称/类型名称/文档id/_update | 修改文档 |
DELETE | localhost:9200/索名称/类型名称/文档id | 删除文档 |
GET | localhost:9200/索引名称/类型名称/文档id | 查询文档通过文档id |
POST | localhost:9200/索引名称/类型名称/_search | 查询所有数据 |
2、添加文档记录
添加单条记录
@Test
void testAddDoc() throws IOException {
// 1.要在指定索引下创建文档,所以要先创建索引,再创建文档
IndexRequest request=new IndexRequest();
// index()方法设置索引名;id()方法设置唯一id标识
request.index("user").id("10001").type("text");
// 2.创建实体类对象,填充数据
User user=new User();
user.setName("张三丰");
user.setAge(30);
// 3.利用jackson将实体类对象转换成JSON格式字符串
request.source(JSON.toJSONString(user), XContentType.JSON);
// 5.发送请求,获取响应结果
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
System.out.println("_index: "+response.getIndex());
System.out.println("_id: "+response.getId());
System.out.println("_result: "+response.getResult());
}
批量添加记录
@Test
void testBulkRequest()throws IOException{
BulkRequest bulkRequest = new BulkRequest();
ArrayList<Employee> users = new ArrayList<>();
// users.add(new Employee("李文",23,"研发工程师","2352"));
// users.add(new Employee("罗文",17,"测试工程师","8732"));
// users.add(new Employee("徐洁",22,"算法工程师","8791"));
// users.add(new Employee("罗辑",31,"高级研发工程师","8765"));
// users.add(new Employee("叶文洁",70,"资深研发工程师","8551"));
users.add(new Employee("小猪佩奇",23,"猪","2"));
users.add(new Employee("小猪",17,"佩奇","4"));
users.add(new Employee("测试",22,"小","6"));
users.add(new Employee("xiaozhubeiqi",31,"peiqi","8"));
users.add(new Employee("小猪佩佩",70,"小猪佩祺过大年","10"));
users.add(new Employee("小猪珮奇",23,"小猪佩祺过大年","12"));
users.add(new Employee("小猪佩奇",23,"小猪佩奇过大年","14"));
for(int i = 0;i< users.size();i++){
bulkRequest.add(new IndexRequest("pig").id(""+(i+1)).type("pinyin")
.source(JSON.toJSONString(users.get(i)),XContentType.JSON));
}
BulkResponse bulkResponse = client.bulk(bulkRequest,RequestOptions.DEFAULT);
System.out.println(!bulkResponse.hasFailures());
}
3、更新文档记录
@Test
void testUpdateDoc() throws IOException
{
UpdateRequest request = new UpdateRequest("test_index","random","1");
User user = new User("张三",18,"003");
request.doc(JSON.toJSONString(user), XContentType.JSON);
UpdateResponse updateResponse = client.update(request, RequestOptions.DEFAULT);
System.out.println(updateResponse.status() == RestStatus.OK);
}
4、删除文档记录
@Test
void testDelete() throws IOException {
HttpHost host = HttpHost.create("http://localhost:9200");
client = new RestHighLevelClient(RestClient.builder(host));
DeleteRequest request = new DeleteRequest("test_index","random","1");
DeleteResponse deleteResponse = client.delete(request, RequestOptions.DEFAULT);
System.out.println(deleteResponse.status() == RestStatus.OK);
}
九、高级查询
1、排序查询
/**
* 排序查询(sort) 代码同matchAllQuery
* 匹配查询符合条件的所有数据,并设置分页
*/
@Test
public void sortQuery() {
try {
// 构建查询条件
MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
// 创建查询源构造器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(matchAllQueryBuilder);
// // 设置分页
// searchSourceBuilder.from(0);
// searchSourceBuilder.size(3);
// 设置排序
searchSourceBuilder.sort("id", SortOrder.ASC);
// 创建查询请求对象,将查询对象配置到其中
SearchRequest searchRequest = new SearchRequest("employee_alias");
searchRequest.source(searchSourceBuilder);
// 执行查询,然后处理响应结果
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
// 根据状态和数据条数验证是否返回了数据
if (RestStatus.OK.equals(searchResponse.status())) {
SearchHits hits = searchResponse.getHits();
for (SearchHit hit : hits) {
// 将 JSON 转换成对象
Employee userInfo = JSON.parseObject(hit.getSourceAsString(), Employee.class);
// 输出查询信息
log.info(userInfo.toString());
}
}
} catch (IOException e) {
log.error("", e);
}
}
2、聚合查询(一)
查询30岁以上、30岁及以下员工的平均年龄:
@Test
public void bucketQuery() {
// 创建查询源构造器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 创建查询请求对象,将查询对象配置到其中
SearchRequest searchRequest = new SearchRequest("employee");
RangeAggregationBuilder rangeAggregationBuilder = AggregationBuilders.range("age_ranges_avg")
.field("age")
.addRange(0, 30)
.addRange(31, 100).subAggregation(AggregationBuilders.avg("avgAge").field("age"));
searchSourceBuilder.aggregation(rangeAggregationBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse response;
try {
//发起请求,获取响应结果
response = client.search(searchRequest, RequestOptions.DEFAULT);
//获取聚合的结果
Aggregations aggregations = response.getAggregations();
Aggregation aggregation = aggregations.get("age_ranges_avg");
System.out.println(JSON.toJSONString(aggregation));
//获取桶聚合结果
List<? extends Range.Bucket> buckets = ((Range) aggregation).getBuckets();
//循环遍历各个桶结果
for (Range.Bucket bucket : buckets) {
//分组的key
String key = bucket.getKeyAsString();
//分组的值
long docCount = bucket.getDocCount();
ParsedAvg avgAge = bucket.getAggregations().get("avgAge");
System.out.println(key + "======平均年龄:" + avgAge.getValue() + "======数量:" + docCount);
}
} catch (IOException e) {
e.printStackTrace();
}
}
3、聚合查询(二)
/**
* 聚合查询
* Metric 指标聚合分析
*/
@Test
public void metricQuery() {
try {
// 构建查询条件
MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
// 创建查询源构造器
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(matchAllQueryBuilder);
// 获取最贵的商品
AggregationBuilder maxAge = AggregationBuilders.max("maxAge").field("age");
searchSourceBuilder.aggregation(maxAge);
// 获取最便宜的商品
AggregationBuilder minAge = AggregationBuilders.min("minAge").field("age");
searchSourceBuilder.aggregation(minAge);
// 创建查询请求对象,将查询对象配置到其中
SearchRequest searchRequest = new SearchRequest("employee");
searchRequest.source(searchSourceBuilder);
// 执行查询,然后处理响应结果
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
Aggregations aggregations = searchResponse.getAggregations();
ParsedMax max = aggregations.get("maxAge");
log.info("最年长:" + max.getValue());
ParsedMin min = aggregations.get("minAge");
log.info("最年轻:" + min.getValue());
} catch (IOException e) {
log.error("", e);
}
}
4、模糊查询
//模糊查询,原理是构建DFA,查询名字中含有“文”的员工
@Test
public void fuzzyQuery() {
try {
// 构建查询条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.fuzzyQuery("name", "洁").fuzziness(Fuzziness.AUTO));
// 创建查询请求对象,将查询对象配置到其中
SearchRequest searchRequest = new SearchRequest("employee");
searchRequest.source(searchSourceBuilder);
// 执行查询,然后处理响应结果
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
// 根据状态和数据条数验证是否返回了数据
if (RestStatus.OK.equals(searchResponse.status())) {
SearchHits hits = searchResponse.getHits();
for (SearchHit hit : hits) {
// 将 JSON 转换成对象
Employee userInfo = JSON.parseObject(hit.getSourceAsString(), Employee.class);
// 输出查询信息
log.info(userInfo.toString());
}
}
} catch (IOException e) {
log.error("", e);
}
}
5、范围查询
//查询20岁以上的员工
@Test
public void rangeQuery() {
try {
// 构建查询条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.rangeQuery("age").gte(20));
// 创建查询请求对象,将查询对象配置到其中
SearchRequest searchRequest = new SearchRequest("employee");
searchRequest.source(searchSourceBuilder);
// 执行查询,然后处理响应结果
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
// 根据状态和数据条数验证是否返回了数据
if (RestStatus.OK.equals(searchResponse.status()) ) {
SearchHits hits = searchResponse.getHits();
//log.info(hits.getTotalHits().value + "");
for (SearchHit hit : hits) {
// 将 JSON 转换成对象
Employee userInfo = JSON.parseObject(hit.getSourceAsString(), Employee.class);
// 输出查询信息
log.info(userInfo.toString());
}
}
} catch (IOException e) {
log.error("", e);
}
}
6、多字段查询
multi_match进行多字段匹配查询,进行权重控制
GET pig/_search
{
"query": {
"multi_match": {
"query": "小猪佩奇",
"fields": ["name^3","occupation"]
}
}
}
@Test
public void matchQuery() {
try {
// 构建查询条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
Map<String,Float> fields = new HashMap(2);
fields.put("name", 1.0f);
fields.put("occupation", 1.0f);
// QueryBuilder queryBuilder = null;
// queryBuilder.must(QueryBuilders.multiMatchQuery("name","小猪佩奇").fields(fields).analyzer("ik_smart"));
searchSourceBuilder.query(QueryBuilders.multiMatchQuery("小猪佩奇","name","occupation").fields(fields).analyzer("pinyin"));
// 创建查询请求对象,将查询对象配置到其中
SearchRequest searchRequest = new SearchRequest("pig");
searchRequest.source(searchSourceBuilder);
// 执行查询,然后处理响应结果
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
// 根据状态和数据条数验证是否返回了数据
if (RestStatus.OK.equals(searchResponse.status()) ) {
SearchHits hits = searchResponse.getHits();
for (SearchHit hit : hits) {
// 将 JSON 转换成对象
Employee userInfo = JSON.parseObject(hit.getSourceAsString(), Employee.class);
// 输出查询信息
log.info(userInfo.toString());
}
}
} catch (IOException e) {
log.error("", e);
}
}