该教程主要分为 三篇文章。此为第一篇——主要介绍 ElasticSearch、Kibana 的安装 以及如何 通过 Http 和Java API的方式使用 ElasticSearch。学完本文,你就可以 在SpringBoot 项目中使用 ES了。第二篇超链接、第三篇超链接
一、实现ElasticSearch 单机运行
1.1 安装运行ElasticSearch
首先,我们可以在 ElasticSearch官网下载 7.10.2版本,这里给出window版下载地址:
https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.10.2-windows-x86_64.zip
该版本使用的是java jdk1.8,下载到本地后,直接解压到你决定的路径下(例如:E:\development\elasticsearch\)
运行其 bin文件夹下的 elasticsearch.bat,es 开始运行,并默认使用端口 9200向外界提供服务。
浏览器访问 localhost:9200 可查看 es的相关信息,以校验运行是否成功
1.2 安装运行Kibana
同时,如果你想更加方便的使用 ElasticSearch,可以下载 Kibana。Kibana类似于 Naciate等数据库管理软件,提供可视化的管理界面,7帮助你操作 ElasticSearch。因为我们下载的ES版本是 7.10.2 ,所以 Kibana 也选择使用 7.10.2 版本。这里给出下载地址:https://artifacts.elastic.co/downloads/kibana/kibana-7.10.2-windows-x86_64.zip 建议使用迅雷下载,浏览器下载较慢。
- 下载解压到本地后,修改其 config 文件夹下的配置文件 kibana.yml,保证以下内容生效:
server.port: 5601
elasticsearch.hosts: ["http://localhost:9200"]
i18n.locale: "zh-CN" #设置默认语言为中文
- 修改配置之后,双击bin 文件夹下的 kibana.bat,即可启动 Kibana 。在地址:http://localhost:5601/ 即可访问当Kibana页面。
二、ElasticSearch基础操作
2.1 HTTP方式操作 ES
使用Postman发送http请求到 ES 来实现对 ES的操作
2.1.1 操作索引
-
索引-创建:
postman发送 Put 请求:
localhost:9200/shopping // 其中 localhost:9200 -> es所在机器 ip // shopping -> 希望新建索引名称
请求返回:
{ "acknowledged": true, //表明 创建成功 "shards_acknowledged": true, //表明 分片分配成功 "index": "shopping" //索引名称 }
-
索引-查看索引信息
Postman发送 Get 请求:
localhost:9200/shopping
请求返回:
{ "shopping": { "aliases": {}, "mappings": {}, "settings": { "index": { "routing": { "allocation": { "include": { "_tier_preference": "data_content" } } }, "number_of_shards": "1", "provided_name": "shopping", "creation_date": "1651737136026", "number_of_replicas": "1", "uuid": "qEAGozjASpqbBl9p1gFmbw", "version": { "created": "7100299" } } } } }
-
索引-查看ES中所有索引
Postman发送 Get 请求:
localhost:9200/_cat/indices?v // 加上 ?v 是展示索引 详细 信息
请求返回:
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size green open .apm-custom-link PtMtWtlDR-SO8dlk_T9wTA 1 0 0 0 208b 208b green open .kibana_task_manager_1 QPx1WNAqSd-aevNgUj-2wg 1 0 5 48 48.5kb 48.5kb green open .apm-agent-configuration Sa1lFlJDRkOWjT9X-QUjWA 1 0 0 0 208b 208b green open .async-search cPqqbj48QzS9W5Yplk9mBQ 1 0 1 0 29.3kb 29.3kb green open kibana_sample_data_flights 2DaAg0rtSyqHjn-kog0HfQ 1 0 13059 0 5.6mb 5.6mb green open .kibana-event-log-7.10.2-000001 mGeBIM_LRiOQ0AsamKwMGw 1 0 1 0 5.6kb 5.6kb green open .kibana_1 rsmoI7DyRgW6Npm0ZCLOmA 1 0 95 10 2.1mb 2.1mb yellow open shopping qEAGozjASpqbBl9p1gFmbw 1 1 0 0 208b 208b
-
索引-删除
Postman发送 DELETE 请求:
localhost:9200/shopping
2.1.2 操作文档
-
文档-创建
索引创建完毕后,就可以创建文档了。ES中的文档类似于MySQL中的表数据(表中的1条记录)。
Postman发送 Post 请求
localhost:9200/shopping/_doc //添加 数据,id 由 ES 自动生成 localhost:9200/shopping/_doc/0001 //添加 0001 后,将使用 0001 作为数据的唯一id localhost:9200/shopping/_create/0001 //同上效果
请求体内容:
{ "title":"华为Mate40", "category":"华为", "images":"https://", "price":5800 }
请求返回:
{ "_index": "shopping", "_type": "_doc", "_id": "32mMk4ABYnhfGB3XaX2d", //数据的唯一标识(自动生成/自定义),类似主键 "_version": 1, "result": "created", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 0, "_primary_term": 1 }
-
文档-查询(主键查询)
localhost:9200/shopping/_doc/0001 //使用Get方式请求
请求返回:
{ "_index": "shopping", "_type": "_doc", "_id": "0001", "_version": 1, "_seq_no": 1, "_primary_term": 1, "found": true, "_source": { "title": "华为Mate40", "category": "华为", "images": "https://", "price": 5800 } }
-
文档-全查询
localhost:9200/shopping/_search //使用Get方式请求
请求将返回全部文档
-
文档-完全覆盖修改
localhost:9200/shopping/_doc/0001 //使用Put方式请求
请求体 json格式(同添加时一样,放在请求体中):
{ "title": "华为Mate40", "category": "华为", "images": "https://xiugai", "price": 5800 }
请求返回:
{ "_index": "shopping", "_type": "_doc", "_id": "0001", "_version": 2, "result": "updated", //修改成功 "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 2, "_primary_term": 1 }
-
文档-局部修改
localhost:9200/shopping/_update/0001 //Post方式请求
请求体:
{ "doc" : { "price" : 5900 //填写需要修改的字段 } }
-
文档-删除
localhost:9200/shopping/_doc/0001 //DELETE方式请求
请求返回:
{ "_index": "shopping", "_type": "_doc", "_id": "0001", "_version": 4, "result": "deleted", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 4, "_primary_term": 1 }
2.1.3 文档-高级查询
-
条件查询
该请求将查询 shopping索引中 字段 category 字段值为 华为 的文档
localhost:9200/shopping/_search?q=category:华为 //Get请求
这种方式 是将请求参数放在 URL 路径上,该方式虽然便捷,但是可能存在乱码或者请求头过长等问题。所以还可以将请求参数放在请求体中, 如下:
localhost:9200/shopping/_search //请求路径(后续几个查询,都使用此路径) //请求体: { "query" : { "match" : { "category" : "华为" } } }
全量查询,可以将 match更改为match_all 。当然全量查询数据量过大,所以一般分页查询。
-
分页查询
{ "query" : { "match" : { "category" : "华为" } }, "from" : 0, //分页起始位置 "size" : 100 //每页最多100条记录 }
-
查询文档指定字段
{ "query" : { "match" : { "category" : "华为" } }, "_source" : ["title"] //只查看文档的title字段 }
-
指定字段排序
{ "query" : { "match" : { "category" : "华为" } }, "sort" : { "price" : { //根据price字段进行排序操作 "order" : "asc" } } }
-
多条件查询
- must:多条件必须同时成立
- should:满足一个条件即可
- filter:范围查询
{ "query" : { "bool" : { "must" : [ // 此位置可以使用must、should { "match" : { "category" : "华为" } }, { "match" : { "price" : 5900 } } ], "filter" : { "range" : { "price" : { //筛选价格字段值大于5000的 "gt" : 5000 } } } } } }
-
全文检索
如果match字段中category为 华 ,其实也是可以查询到的。这是因为当保存文档数据时,es会将文字进行分词进行拆解操作,将拆解后的数据进行倒排索引中。这样即使使用文字的一部分,也可以查询到文档。这种检索方式,即全文检索。
当然如果你不希望使用这种全文检索,可以将 match字段 更改为 match_phrase
-
高亮显示
这里的高亮显示,其实是 ES 会对结果中 指定字段进行 特殊高亮处理。前端可以拿到这个 高亮字段 进行 字段的高亮显示。比如这里我们使用 match 全文检索华 ,那么文档 category字段中 符合检索条件的 内容会被高亮显示。
{ "query" : { "match" : { "category" : "华" } }, "highlight" : { "fields" : { "category" : {} } } }
不太理解的话,可以看看百度。搜索 华 。检索到的很多内容标题 中 符合检索条件——华 的部分高亮显示了。
-
聚合查询
- term:分组
- avg:平均值
{ "aggs" : { //聚合操作 "price_group" : { //统计结果的名称(自定义) "terms" : { //操作类别:term、avg "field" : "price" } } } }
2.1.4 文档-映射关系
先创建一个新的索引来演示:
localhost:9200/user //Put方式请求
然后设置该索引文档映射关系:
localhost:9200/user/_mapping //Put方式请求
请求体:
{
"properties" : {
"name" : {
"type" : "text", //文本内容
"index" : true //能够被索引,即支持该字段的查询
},
"sex" : {
"type" : "keyword", //不能分词,查询时必须完全匹配
"index" : true
},
"tel" : {
"type" : "keyword",
"index" : false
}
}
}
这个的作用就是对索引中 所有文档的字段进行设置。比如字段类型(不同检索规则)、是否能够被索引。
2.2 Java API 方式操作 ES(SpringBoot集成ES)
这里给大家提供一个 SpringBoot 的Maven项目 帮助大家直接上手。将项目下拉到本地后,可以先看一下项目的README.md。
github地址:https://github.com/kongxiaoran/elasticsearch-learning
对下面对 ES 操作的 代码 在项目的 ElasticSearchLearningApplicationTests 类中
2.2.1 操作索引
-
索引-创建
//创建请求 CreateIndexRequest request = new CreateIndexRequest("users"); //执行请求,使用默认的请求配置 CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT); System.out.println("创建索引 "+ ((response.isAcknowledged()==true)?"成功了":"失败了"));
-
索引-查询
//创建请求 GetIndexRequest request = new GetIndexRequest("users"); boolean exists = client.indices().exists(request, RequestOptions.DEFAULT); System.out.println("索引"+(exists==true?"":"不")+"存在"); if(exists){ GetIndexResponse getIndexResponse = client.indices().get(request,RequestOptions.DEFAULT); System.out.println(getIndexResponse.getAliases()); System.out.println(getIndexResponse.getMappings()); System.out.println(getIndexResponse.getSettings()); }
-
索引-删除
DeleteIndexRequest request = new DeleteIndexRequest("test1"); AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT); System.out.println(delete.isAcknowledged());//删除成功返回true,失败返回false
2.2.2 操作文档
-
文档-添加
//创建添加数据 User user = new User("张三",23,"男"); //声明要保存到那个索引库 IndexRequest request = new IndexRequest("users"); request.id("001").timeout("1s"); //给请求放入数据.向ES中插入数据,必须将数据转换成 JSON 格式.将数据转化成JSON字符串的方法,可自选 request.source(JSON.toJSONString(user), XContentType.JSON); //request.source(new ObjectMapper().writeValueAsString(user),XContentType.JSON); //执行请求 IndexResponse resp = client.index(request, RequestOptions.DEFAULT); System.out.println(resp);//和我们使用命令添加时显示的差不多
-
文档-更新
//声明修改数据 User user = new User(); user.setAge(32); //修改之前为 23 //声明索引库 UpdateRequest request = new UpdateRequest("users","001"); request.id("001").timeout("1s");//设置修改的文档id和请求超时时间 request.doc(JSON.toJSONString(user),XContentType.JSON); // request.doc(XContentType.JSON,"age",32); 适合局部修改 //执行修改 修改的时候,如果对象中某个字段没有给值,那么也会修改成默认值 UpdateResponse update = client.update(request,RequestOptions.DEFAULT); System.out.println(update); System.out.println(update.status());
-
文档-查看文档是否存在
GetRequest request = new GetRequest("users","001"); boolean exists = client.exists(request, RequestOptions.DEFAULT); System.out.println(exists);//存在返回true,不存在返回false
-
文档-根据id获取文档
GetRequest request = new GetRequest("users","001"); GetResponse resp = client.get(request, RequestOptions.DEFAULT); System.out.println(resp); System.out.println(resp.getSourceAsString());//获取文档内容的字符串,没有数据为null
-
文档-删除
DeleteRequest request = new DeleteRequest("users","001"); DeleteResponse delete = client.delete(request, RequestOptions.DEFAULT); System.out.println(delete); System.out.println(delete.status());
-
文档-批量新增
BulkRequest bulkRequest = new BulkRequest(); bulkRequest.timeout("10s"); List<User> list = new ArrayList<>(); list.add(new User("chen1",20,"男")); list.add(new User("chen2",21,"男")); list.add(new User("chen3",22,"男")); list.add(new User("chen4",23,"男")); list.add(new User("chen5",24,"男")); list.add(new User("chen6",25,"男")); list.add(new User("chen7",26,"男")); list.add(new User("chen8",27,"男")); //注意:id要是重复,则会覆盖掉 for (int i = 0; i < list.size(); i++) { bulkRequest.add(new IndexRequest("users") .id(""+(i+1)) .source(JSON.toJSONString(list.get(i)), XContentType.JSON)); } //执行 BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT); System.out.println(bulk); System.out.println(bulk.status());
-
文档-批量删除
BulkRequest bulkRequest = new BulkRequest(); bulkRequest.timeout("10s"); for (int i = 0; i < 8; i++) { bulkRequest.add(new DeleteRequest("users",""+(i+1))); } //执行 BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT); System.out.println(bulk); System.out.println(bulk.status());
2.2.3 文档-高级查询
-
文档-条件查询
//声明请求 SearchRequest request = new SearchRequest("users"); //创建查询构造器对象 SearchSourceBuilder builder = new SearchSourceBuilder(); //精准查询条件构造器,还可以封装很多的构造器,都可以使用QueryBuilders这个类构建 //QueryBuilders里面封装了我们使用的所有查询筛选命令 TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "chen1"); //把查询条件构造器放入到查询构造器中 builder.query(termQueryBuilder); //把条件构造器放入到请求中 request.source(builder); //执行查询 SearchResponse search = client.search(request, RequestOptions.DEFAULT); //这个查询就和我们使用命令返回的结果是一致的 System.out.println(JSON.toJSONString(search.getHits().getHits())); System.out.println("=============================================="); for (SearchHit hit : search.getHits().getHits()) { //遍历获取到的hits,让每一个hit封装为map形式 System.out.println(hit.getSourceAsMap()); }
-
分页查询
//声明请求 SearchRequest request = new SearchRequest("users"); //创建查询构造器对象 TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "chen1"); // * 把条件构造器放入到请求中。这里初始查询构造器时就设置了分页的size与from request.source(new SearchSourceBuilder().from(0).size(100).query(termQueryBuilder)); //执行查询 SearchResponse search = client.search(request, RequestOptions.DEFAULT); //这个查询就和我们使用命令返回的结果是一致的 System.out.println(JSON.toJSONString(search.getHits().getHits())); System.out.println("=============================================="); for (SearchHit hit : search.getHits().getHits()) { //遍历获取到的hits,让每一个hit封装为map形式 System.out.println(hit.getSourceAsMap()); }
-
查询文档-按指定字段值排序
剩余代码同上,只将上方第7行代码更改为:
//把条件构造器放入到请求中。这里初始查询构造器时就设置了分页的size与from以及排序规则 request.source(new SearchSourceBuilder().from(0).size(100).sort("age",SortOrder.DESC).query(termQueryBuilder));
-
查询文档-过滤文档中一些不需要的字段,只显示需要的字段
//把条件构造器放入到请求中。这里初始查询构造器时就设置了分页的size与from以及排序规则 request.source(new SearchSourceBuilder().from(0).size(100).sort("age", SortOrder.DESC) .fetchSource(new String[]{"name"},new String[]{}).query(termQueryBuilder));
-
组合查询
//初始化条件构造器:设置组合查询 BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); // 必须 age = 24 && sex != "男" // boolQueryBuilder.must(QueryBuilders.matchQuery("age",24)); // boolQueryBuilder.mustNot(QueryBuilders.matchQuery("sex","男")); // 必须 age = 24 || sex = "男" boolQueryBuilder.should(QueryBuilders.matchQuery("age",24)); boolQueryBuilder.should(QueryBuilders.matchQuery("sex","男")); //把条件构造器放入到请求中。这里初始查询构造器时就设置了分页的size与from以及排序规则,然后查询构造器再执行 request.source(new SearchSourceBuilder().from(0).size(100).sort("age", SortOrder.DESC) .fetchSource(new String[]{"name"},new String[]{}).query(boolQueryBuilder));
-
范围查询
SearchRequest request = new SearchRequest(); request.indices("users"); SearchSourceBuilder builder = new SearchSourceBuilder(); RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age"); rangeQueryBuilder.gte(25).lt(30); // 25<= x <30 builder.query(rangeQueryBuilder); request.source(builder); SearchResponse response = client.search(request, RequestOptions.DEFAULT); SearchHits hits = response.getHits(); for (SearchHit hit : hits) { System.out.println(hit.getSourceAsString()); }
-
范围查询 && 模糊查询
前面我们基本都是使用 单种 查询。这里演示一下,同时对不同字段执行不同类型查询的 操作
SearchRequest request = new SearchRequest().indices("users"); SearchSourceBuilder builder = new SearchSourceBuilder(); // name 字段进行模糊查询 寻找 符合 chen ,可容忍误差在 1个字符内 FuzzyQueryBuilder fuzzinessBuild = QueryBuilders.fuzzyQuery("name", "chen").fuzziness(Fuzziness.ONE); RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age").gte(22).lt(30); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery().must(fuzzinessBuild).must(rangeQueryBuilder); builder.query(boolQueryBuilder); request.source(builder); SearchResponse response = client.search(request, RequestOptions.DEFAULT); SearchHits hits = response.getHits(); for (SearchHit hit : hits) { System.out.println(hit.getSourceAsString()); }
-
高亮查询
SearchSourceBuilder builder = new SearchSourceBuilder(); TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "chen"); builder.query(termQueryBuilder).highlighter(); //将 termQuery 查询的内容 高亮显示 SearchResponse response = client.search(new SearchRequest().indices("users"). source(builder),RequestOptions.DEFAULT); SearchHits hits = response.getHits(); for (SearchHit hit : hits) { System.out.println(hit.getSourceAsString()); }
-
聚合查询
-
最大值查询文章来源:https://www.toymoban.com/news/detail-409737.html
SearchSourceBuilder builder = new SearchSourceBuilder(); builder.aggregation(AggregationBuilders.max("maxAge").field("age")); SearchResponse response = client.search(new SearchRequest().indices("users").source(builder) ,RequestOptions.DEFAULT); SearchHits hits = response.getHits(); //查询到的最大值的情况 System.out.println(JSON.toJSONString(response.getAggregations())); for (SearchHit hit : hits) { System.out.println(hit.getSourceAsString()); }
-
分组查询文章来源地址https://www.toymoban.com/news/detail-409737.html
SearchSourceBuilder builder = new SearchSourceBuilder(); builder.aggregation(AggregationBuilders.terms("age").field("age")); SearchResponse response = client.search(new SearchRequest().indices("users").source(builder) ,RequestOptions.DEFAULT); SearchHits hits = response.getHits(); //查询到的分组情况 System.out.println(JSON.toJSONString(response.getAggregations())); for (SearchHit hit : hits) { System.out.println(hit.getSourceAsString()); }
-
到了这里,关于ElasticSearch保姆级教程[1]——SpringBoot 项目中使用 ES的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!