ElasticSearch入门学习
es简介(是什么)
- 概念
**Elasticsearch 是一个实时的分布式存储、搜索、分析的引擎,使用一种称为 **倒排索引的结构,它适用于快速的全文搜索。一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表。
- 背景
Elasticsearch由一些Elasticsearch进程(Node)组成集群(cluster),用来存放索引(Index)。为了存放数据量很大的索引,Elasticsearch将Index切分成多个分片(Shard),在这些Shard里存放一个个的文档(document)。通过这一批shard组成一个完整的index。并且,每个Shard可以设置一定数量的副本(Replica),写入的文档同步给副本Shard,副本Shard可以提供查询功能,分摊系统的读负载。在主Shard所在Node(ES进程)挂掉后,可以提升一个副本Shard为主Shard,文档继续写在新的主Shard上,来提升系统的容灾能力。
es中名词及解释
集群(cluster)/节点(node)
es本身就是一个集群,去中心化,无中心节点。假设索引index配置了10个分片,1个副本,那么总共的分片数应该是20个,10 *(1+1),那么最大的Elasticsearch节点数应该就是20。
最大节点数 = 分片数 ✖ (副本数+1)
分片(shards)
代表索引分片,es可以把一个完整的索引分成多个分片,这样的好处是可以把一个大的索引拆分成多个,分布到不同的节点上。构成分布式搜索。分片的数量只能在索引创建前指定,并且索引创建后不能更改。
路由(routing)
在存入时通过路由键将数据存入指定分片,在查询的时候可以通过相同的路由键指明在哪个分片将数据查出来。
只查询一个shard,避免在其他shard无用的查询与master上的合并,提升了查询效率。
索引(index)
es数据管理得顶层单位,类似关系型数据库中得数据库。等同于mysql中的database,数据库。
类型(type)
目前已弃用,类似mysql中的表,即分类。
文档(document)
一条数据就是一个文档。类似MySQL中的row。
字段(fields)
类似mysql中的column。
关系对比:
Elasticsearch --------------> Index------------->Type------>Documents------->Fields
RelationDB ---------------->Databases------->Table------>Rows--------------->Columns
es与solr对比
Solr与ES都是基于java/lucence来做一套面向文档结构的Nosql结构的数据库
-
分布式solr 分布式 需要结合zookeeper 来实现,ES 自身有相关分布式协调。
-
支持的数据结构solr支持 xml json html 等多种数据结构,而ES 仅支持json这种结构。
-
性能solr在新建索引时是IO阻塞的,如果在新建索引时同时进行搜索,ES来的相对较快。所以在实时性上,ElasticSearch 相比还是更好的选择。
总结:如果单纯的对已有数据进行查询,那么solr查询效果更快。
常用命令行(基于kibana操作)
索引操作
-
创建索引 PUT/索引名
-
查询索引 GET/索引名
-
删除索引 DELETE/索引名
-
创建规则(设置属性)
text属性与keyword属性**Text:**会分词,然后进行索引支持模糊、精确查询不支持聚合
**keyword:**不进行分词,直接索引支持模糊、精确查询支持聚合
文档操作
-
创建文档 PUT/索引名/文档id
-
更新文档 POST/索引名/文档id/_update
-
删除文档 DELETE/索引名/文档id
-
查询文档
-
"must"属性,跟mysql中的and类似
-
"should"属性,跟mysql中的or类似
-
"must_not"属性,跟mysql中!=类似
-
"bool" 使用多个条件匹配
-
"match"属,模糊查找,会使用分词器
-
"term",精确产找,不会使用分词器
-
springboot集成es
- 引入依赖
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.12.0</version>
</dependency>
-
构建es客户端对象,并纳入容器管理
RestHighLevelClient client = new RestHighLevelClient( RestClient.builder( new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 9201, "http"))); client.close();
-
创建索引
/** * 创建索引 */ @Test void createIndex() throws IOException { //创建索引请求 CreateIndexRequest createIndexRequest = new CreateIndexRequest("cz-es"); //客户端执行请求,获取相应结果 CreateIndexResponse response = client.indices().create(createIndexRequest, RequestOptions.DEFAULT); System.out.println(response); }
-
判断索引是否存在
/** * 判断索引是否存在 */ @Test void existIndex() throws IOException { //创建索引请求 GetIndexRequest getIndexRequest = new GetIndexRequest("cz-es"); //客户端执行请求,获取相应结果 boolean exists = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT); System.out.println(exists); }
-
删除索引
/** * 删除索引 */ @Test void deleteIndex() throws IOException { //创建索引请求 DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("cz-es"); //客户端执行请求,获取相应结果 AcknowledgedResponse delete = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT); System.out.println(delete.isAcknowledged() ); }
-
创建文档
/** * 创建文档 */ @Test void createDoc() throws IOException { User user = new User("cz", 18); //创建索引请求 IndexRequest request = new IndexRequest("cz-es"); //客户端执行请求,获取相应结果 //指令 PUT/cz-es/_doc/1 request.id("1"); request.timeout(TimeValue.timeValueSeconds(1)); request.source(JSON.toJSONString(user), XContentType.JSON); IndexResponse index = client.index(request, RequestOptions.DEFAULT); System.out.println(index); }
-
获取文档
/** * 获取文档 */ @Test void getDoc() throws IOException { GetRequest getRequest = new GetRequest("cz-es", "2"); //不查询_source内容,效率更快,如果加了一下设置,返回的response中获取不到source // getRequest.fetchSourceContext(new FetchSourceContext(false)); // getRequest.storedFields("_none"); //先判断索引库是否存在 boolean exists = client.exists(getRequest, RequestOptions.DEFAULT); System.out.println(exists); if (exists) { //创建获取文档请求 GetResponse response = client.get(getRequest, RequestOptions.DEFAULT); System.out.println(response.getSourceAsString()); System.out.println(response); } }
-
更新文档
/** * 更新文档 */ @Test void updateDoc() throws IOException { UpdateRequest updateRequest = new UpdateRequest("cz-es", "1"); updateRequest.timeout("1s"); User cz3 = new User("cz4", null); updateRequest.doc(JSON.toJSONString(cz3), XContentType.JSON); UpdateResponse update = client.update(updateRequest, RequestOptions.DEFAULT); System.out.println(update); }
-
删除文档
/** * 删除文档 */ @Test void deleteDoc() throws IOException { DeleteRequest deleteRequest = new DeleteRequest("cz-es", "2"); deleteRequest.timeout("1s"); DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT); System.out.println(deleteResponse.status()); }
-
批量插入文档
/** * 批量插入数据 */ @Test void batchInsertDoc() throws IOException { ArrayList<User> users = new ArrayList<>(); users.add(new User("cz1", 11)); users.add(new User("cz2", 12)); users.add(new User("cz3", 13)); users.add(new User("cz4", 14)); //创建批量插入请求 BulkRequest bulkRequest = new BulkRequest("cz-es"); bulkRequest.timeout("10s"); for (int a = 0; a < users.size(); a++) { bulkRequest.add(new IndexRequest("cz-es") .source(JSON.toJSONString(users.get(a)), XContentType.JSON) ); } BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT); System.out.println(bulk.hasFailures());//判断是否失败,false代表不是失败,即成功。 }
-
搜索
/** * 搜索 */ @Test void search() throws IOException { //创建索引库的搜索请求 searchRequest //搜索条件构造 searchSourceBuilder //高亮构造 highLightBuilder //精确查询构造 termQueryBuilder //模糊查询构造 matchAllQueryBuilder SearchRequest searchRequest = new SearchRequest("cz-es"); //构建搜索条件 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //QueryBuilders.termQuery精确匹配 //QueryBuilders.matchAllQuery 查询所有 TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name","cz1" ); // MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery(); searchSourceBuilder.query(termQueryBuilder); //设置超时 searchSourceBuilder.timeout(new TimeValue(2, TimeUnit.SECONDS)); searchRequest.source(searchSourceBuilder); //执行请求 SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT); System.out.println(JSON.toJSONString(search.getHits())); for (SearchHit hit : search.getHits().getHits()) { System.out.println(hit.getSourceAsMap());//打印具体查询到的数据 } }