- 一、ElasticSearch简介
- 二、数据库 *** 作(HTTP请求 *** 作ES)
- 1.数据格式
- 2.索引 *** 作(不支持POST)
- 3.文档 *** 作/数据 *** 作(增删改查)
- 4.条件/分页/查询,排序,筛选字段
- 5.多条件查询
- 6.全文检索/全文匹配/高亮查询
- 7.聚合查询
- 8.mapping
- 三、Java连接ES(原生态,没有采用SpringBoot搭建)
- 1.环境搭建
- 2.索引 *** 作
- 3.数据添加和修改
- 4.ID获取数据和删除
- 5.批量插入数据
- 6.批量删除数据
- 7.复杂查询
- 8.总结
整理资料参考B站尚硅谷
在之前我们所学mysql数据库,是属于一种结构化数据库,而现实生活中很多数据并非全是结构化的,无法像数据库那样模糊查询匹配数据,由此es诞生,es可以存储海量数据,并且可以毫秒级查询速度。它是分布式、RESTFUL风格的全文搜索和数据分析引擎
二、数据库 *** 作(HTTP请求 *** 作ES)tips:
①在查询过程时不要添加不必要的body内容,不然会报错,
②可以在返回的响应体中result字段查看 *** 作的结果
③字段是在添加JSON数据时同时创建的,也可以在创建数据库之后设置mapping,如果添加数据之后再修改字段的mapping那么可能会失败,同时根据不支持index的字段查询会失败
④通常text类型不支持聚合和排序,需要优化之后才能使用,但是这种text查询时也会进行分词处理
//POST http://localhsot:9200/索引名/_mapping { "properties":{ "province":{"type":"text","fielddata":true} } }
⑤删除索引下全部数据而不改变结构
POST 192.168.100.88:9200/my_index/_delete_by_query
{ "query": { "match_all": {} } }1.数据格式
1)ElasticSearch是一种文档型数据库,一条数据在这里就是一个文档, 2)ElasticSearch和MySQL的比较 3)Type概念逐渐弱化,6.x版本,每一个index中只能有一个type,7.x中,type概念已经被删除 4)倒排索引,传统的结构化mysql数据库查询时是先匹配当前字段,然后找到这一行数据,倒排索引是通过关键字和id的关联,匹配上找到当前id,然后找到当前文章内容2.索引 *** 作(不支持POST)
1)发送post请求失败,不支持POST请求;ncorrect HTTP method for uri [/shopping] and method [POST], allowed: [PUT, DELETE, GET, HEAD]
2)创建索引 post http://localhost:9200/索引名
3)查看索引 get http://localhost:9200/索引名
4)查看所有索引 get http://localhost:9200/_cat/indices?v
5)删除索引 delete http://localhost:9200/索引名
返回字段"acknowledged": true,表示 *** 作成功
1)添加数据 post http://localhost:9200/索引名/_doc/id(可以不写,有随机,如果自定义ID重复,那么会覆盖数据,返回结果的状态时updated,正常添加是created),数据添加在请求体中
这里需要注意一下,在指定id的情况下是可以是可以使用put请求的,也可以将_doc改成_craeated
2)主键查询 get http://localhost:9200/索引名/_doc/id
3)全查询 get http://localhost:9200/索引名/_search
4)修改数据
①全量修改:可以使用原生put/post添加数据的方式覆盖指定id中的所有数据
②增量修改:将body中的数据添加到指定id中,已有的覆盖,没有的添加
post http://localhost:9200/索引名/_update/id,
body:{“doc”:{添加的数据}}
5)指定ID删除 delete http://localhost:9200/索引名/_doc/id
6)删除索引下全部数据而不改变结构
POST 192.168.100.88:9200/my_index/_delete_by_query
{ "query": { "match_all": {} } }4.条件/分页/查询,排序,筛选字段
1)条件查询
在postman中是可以使用get请求发送请求体的,但是浏览器是不支持的
get http://localhost:9200/索引名/_search
get http://localhost:9200/索引名/_search?q=字段名:关键字
条件查询 {“query”:{“match”:{字段名:关键字}}}
全局查询 {“query”:{“match_all”:{}}} ==>使用_search一样可以不加
2)分页查询
{ "query":{ //查询结果集 "match":{ "price":"一块两毛二" //查找的条件 } }, "from":0,//起始位置 "size":2 //长度大小 }
3)筛选查询出来的字段信息
“_source”:[字段1,字段2]
4)排序
“sort”:{“需要排序的字段”:{“order”,“desc/asc”}}
如果字段本身无法排序,那么会报错
1)多条件查询(must&&,should||)
{ "query":{ "bool":{ "must":[{"match":{"name":"华硕笔记本"}},{"match":{"price":"3999"}}] } } }
2)过滤器
{ "query":{ "bool":{ "should":[{"match":{"name":"洗面奶"}},{"match":{"name":"华硕笔记本"}}], "filter":{ "range":{"price":{"gt":1}} } } } }
典型错误,首先会找洗面奶或者华硕笔记本的,但是后面的1价格会再加上白菜的信息
6.全文检索/全文匹配/高亮查询由于IK分词器的存在,es会将字符拆分成多段后存储再倒排索引中,实际上我们输入的关键字只要原文中包含一个及以上就会查询到,在测试中发现,对于英文字符失效
1)准确查询
match_phrase:只有包含这个完整的字段才会匹配,类似mysql中得%关键字%
2)高亮查询
highlight:fields:字段名:{}
{ "query":{ "match_phrase":{"name":"笔记本"} }, "highlight":{ "fields":{"name":{}} } }7.聚合查询
1)根据字段属性的值分组,类似count
{ "aggs":{ "price_doSome":{ // 分组名,随意 "terms":{ //功能:分组,统计price属性值出现的次数 "field":"price" //分组字段 } } }, "size":0 }
2)统计字段的平均值
类似mysql的avg,sum,count(terms),max,min
{ "aggs":{ "price_doSome":{ // 分组名,随意 "avg":{ //功能:平均值,通知字段的平均值 "field":"price" //分组字段 } } }, "size":0 }8.mapping
简单的说字段的数据类型,默认的话字符串是text文本(ik分词器进行分词),数字是long
最好是在建立索引之初还未添加数据的时候就修改mapping,不然后期修改可能会报错
如果不支持index,同样查询会失败
1)查询mapping
GET http://localhost:9200/索引名/_mapping
2)设置mapping
POST http://localhost:9200/索引名/_mapping
{ "properties":{ "name":{ "type":"keyword", //不使用IK分词器,必须全文匹配 "index":true //可以使用索引查询 }, "address":{ "type":"keyword", "index":true } } }三、Java连接ES(原生态,没有采用SpringBoot搭建) 1.环境搭建
1)安装es环境,解压即用,我当前的版本是7.13.0
2)Java项目才maven搭建,运行时部分日志无法打印,可能是版本原因吧
org.elasticsearch elasticsearch7.13.0 org.elasticsearch.client elasticsearch-rest-high-level-client7.13.0 org.apache.logging.log4j log4j-api2.8.2 org.apache.logging.log4j log4j-core2.8.2 com.fasterxml.jackson.core jackson-databind2.9.9
3)测试连接
如果没有报错,那么证明连接成功,记住 *** 作完成之后要及时关闭client,不会因为主程序的停止而停止
public class Estest_Client { public static void main(String[] args) throws IOException { //TransportClient 不再使用 RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("192.168.201.164",9200,"http")) ); client.close(); } }2.索引 *** 作
public class Estest_index { public static void main(String[] args) throws Exception { getIndex(); } public static void createIndex() throws Exception{ RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("192.168.201.164",9200,"http")) ); //创建索引,删除同理DeleteIndexRequest CreateIndexRequest request = new CreateIndexRequest("user"); CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT); //响应状态 boolean acknowledged = response.isAcknowledged(); System.out.println("创建索引是否成功:"+acknowledged); client.close(); } public static void getIndex() throws Exception { RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("192.168.201.164",9200,"http")) ); //查看索引 GetIndexRequest request = new GetIndexRequest(); GetIndexResponse response = client.indices().get(request, RequestOptions.DEFAULT); //响应状态 Map settings = response.getSettings(); Map aliases = response.getAliases(); System.out.println(settings); System.out.println(aliases); } }3.数据添加和修改
public class Estest_doc_add_update { public static void main(String[] args) throws Exception { updateDoc(); } //也可以修改,但是全部修改 public static void createDoc() throws IOException { RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("192.168.201.164",9200,"http")) ); //新建index请求对象 IndexRequest request = new IndexRequest(); request.index("user").id("1001"); User user = new User(); user.setAge(18); user.setName("黎洋"); user.setSex("男"); //封装JSON数据 request.source(new ObjectMapper().writevalueAsString(user), XContentType.JSON); //发起Http请求 IndexResponse response = client.index(request, RequestOptions.DEFAULT); System.out.println(response.getResult());//CREATED client.close(); } //新增字段信息 public static void updateDoc() throws IOException { RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("192.168.201.164",9200,"http")) ); //新建index更新对象 UpdateRequest request = new UpdateRequest(); request.index("user").id("1001"); request.doc(XContentType.JSON,"address","湖北"); //发起Http请求 UpdateResponse response = client.update(request,RequestOptions.DEFAULT); System.out.println(response.getResult());//UPDATED client.close(); } }4.ID获取数据和删除
public class Estest_doc_get_delete { public static void main(String[] args) throws Exception { deleteDocWithId(); } public static void getDocWithId() throws Exception{ RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("192.168.201.164",9200,"http")) ); //创建get对象 GetRequest request = new GetRequest(); request.index("user").id("1001"); GetResponse response = client.get(request, RequestOptions.DEFAULT); System.out.println(response.getField("name"));//不知道获取的什么东西,反正都是NULL System.out.println(response.getSourceAsString()); client.close(); } public static void deleteDocWithId() throws Exception{ RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("192.168.201.164",9200,"http")) ); //创建get对象 DeleteRequest request = new DeleteRequest(); request.index("user").id("1001"); DeleteResponse response = client.delete(request, RequestOptions.DEFAULT); System.out.println(response.toString());//DeleteResponse[index=user,type=_doc,id=1001,version=4,result=deleted,shards=ShardInfo{total=2, successful=1, failures=[]}] client.close(); } }5.批量插入数据
public class Estest_doc_add_batch { public static void main(String[] args) throws Exception { RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("192.168.201.164",9200,"http")) ); //批量 *** 作对象 BulkRequest request = new BulkRequest(); request.add(new IndexRequest().index("user").source(XContentType.JSON,"name","张三333","age",30,"sex","男")); request.add(new IndexRequest().index("user").source(XContentType.JSON,"name","李四333","age",23,"sex","女")); request.add(new IndexRequest().index("user").id("1006").source(XContentType.JSON,"name","王五333","age",12,"sex","男")); BulkResponse response = client.bulk(request, RequestOptions.DEFAULT); System.out.println(response.getTook());//103ms System.out.println(response.getItems());//[Lorg.elasticsearch.action.bulk.BulkItemResponse;@1eb5174b client.close(); } }6.批量删除数据
public class Estest_doc_delete_batch { public static void main(String[] args) throws Exception{ RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("192.168.201.164",9200,"http")) ); //批量 *** 作对象 BulkRequest request = new BulkRequest(); request.add(new DeleteRequest().index("user").id("1001")); request.add(new DeleteRequest().index("user").id("1002")); request.add(new DeleteRequest().index("user").id("1003")); BulkResponse response = client.bulk(request, RequestOptions.DEFAULT); System.out.println(response.getTook());//111ms client.close(); } }7.复杂查询
public class Estest_doc_get_query { public static void main(String[] args) throws Exception { groupQuery(); } public static void match() throws Exception { RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("192.168.201.164",9200,"http")) ); SearchRequest request = new SearchRequest(); request.indices("user"); //全量查询不带任何条件 //单一条件查询-IK分词器 SearchSourceBuilder builder =new SearchSourceBuilder().query(QueryBuilders.termQuery("age","30")); //SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()); //查询-包含张三的角色 // SearchSourceBuilder builder =new SearchSourceBuilder().query(QueryBuilders.matchPhraseQuery("name","张三")); //分页 //排序 // builder.sort("age", SortOrder.ASC); //筛选字段 //builder.fetchSource(new String[]{"name","sex"},new String[]{}); request.source(builder); SearchResponse response = client.search(request, RequestOptions.DEFAULT); SearchHits hits = response.getHits(); //获取命中对象 System.out.println("检索数据条数:"+hits.getTotalHits());//1 hits System.out.println("消耗时间:"+response.getTook());//2ms System.out.println("查询数据的记录条数:"+hits.getHits().length);// for(SearchHit hit : hits.getHits()){ System.out.println(hit.getSourceAsString()); } client.close(); } public static void boolQuery() throws Exception{ RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("192.168.201.164",9200,"http")) ); SearchRequest request = new SearchRequest(); request.indices("user"); SearchSourceBuilder builder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();//查询条件构造器 boolQueryBuilder.must(QueryBuilders.matchQuery("age",30)); boolQueryBuilder.mustNot(QueryBuilders.matchQuery("name","王五")); builder.query(boolQueryBuilder); request.source(builder); SearchResponse response = client.search(request, RequestOptions.DEFAULT); SearchHits hits = response.getHits(); System.out.println("检索数据条数:"+hits.getTotalHits());//1 hits System.out.println("消耗时间:"+response.getTook());//2ms System.out.println("查询数据的记录条数:"+hits.getHits().length);// for(SearchHit hit : hits.getHits()){ System.out.println(hit.getSourceAsString()); } client.close(); } public static void likeSearch() throws Exception{ RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("192.168.201.164",9200,"http")) ); SearchRequest request = new SearchRequest(); request.indices("user"); SearchSourceBuilder builder = new SearchSourceBuilder(); builder.query(QueryBuilders.fuzzyQuery("name","张三").fuzziness(Fuzziness.ONE)); request.source(builder); SearchResponse response = client.search(request, RequestOptions.DEFAULT); SearchHits hits = response.getHits(); System.out.println("检索数据条数:"+hits.getTotalHits());//1 hits System.out.println("消耗时间:"+response.getTook());//2ms System.out.println("查询数据的记录条数:"+hits.getHits().length);// for(SearchHit hit : hits.getHits()){ System.out.println(hit.getSourceAsString()); } client.close(); } public static void highLight() throws Exception{ RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("192.168.201.164",9200,"http")) ); SearchRequest request = new SearchRequest(); request.indices("user"); SearchSourceBuilder builder = new SearchSourceBuilder(); MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", "张三"); HighlightBuilder highlightBuilder = new HighlightBuilder(); highlightBuilder.preTags(""); highlightBuilder.postTags(""); highlightBuilder.field("name"); builder.highlighter(highlightBuilder); builder.query(matchQueryBuilder); request.source(builder); SearchResponse response = client.search(request, RequestOptions.DEFAULT); SearchHits hits = response.getHits(); System.out.println("检索数据条数:"+hits.getTotalHits());//1 hits System.out.println("消耗时间:"+response.getTook());//2ms System.out.println("查询数据的记录条数:"+hits.getHits().length);// for(SearchHit hit : hits.getHits()){ System.out.println(hit.getSourceAsString()); } client.close(); } public static void groupQuery() throws Exception{ RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("192.168.201.164",9200,"http")) ); SearchRequest request = new SearchRequest(); request.indices("user"); SearchSourceBuilder builder = new SearchSourceBuilder(); AggregationBuilder ageBuilder = AggregationBuilders.max("maxAge").field("age"); builder.aggregation(ageBuilder); builder.size(0);//不查询其他数据,只计算聚合函数 request.source(builder); SearchResponse response = client.search(request, RequestOptions.DEFAULT); Aggregations aggregations = response.getAggregations(); List list = aggregations.asList(); System.out.println(list.size()); //System.out.println("最大年龄:"+list.get(0).getmetadata().get("value"));//最大年龄,获取数据为NULL????? System.out.println("命中数据条数:"+ response.getHits().getHits().length);//0 client.close(); } }8.总结
1)查询步骤大致一致
①创建连接对象
②创建SearchRequest对象
③利用SearchSourceBuilders(也可能是其他的构造器)创建符合查询条件的QueryBuilder对象(也可能是其他对象)并且封装到SearchSourceBuilder中,
④设置request的source(SearchSourceBuilder)
⑤设置request的index *** 作的索引
⑥client发起请求获取相应对象和相应的响应结果
⑦关闭client对象
2)实测模糊查询和普通的全文查询没有区别,设置偏差字符个数无效
3)如果没有及时关闭客户端,那么下一次请求可能一直处于等待状态,需要手动在es命令窗口停止关掉socket,ctrl+c
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)