目录
ES简介与使用
ES简介
Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析引擎,能够解决不断涌现出的各种用例。 作为 Elastic Stack 的核心,它集中存储您的数据,帮助您发现意料之中以及意料之外的情况。
一个分布式的实时文档存储,每个字段可以被索引与搜索;
一个分布式实时分析搜索引擎;
能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据。
ES下载
中文下载路径:Download Elasticsearch | Elastic
ES运行
Window环境: 运行elasticsearch.bat文件
Linux环境: 执行命令./elasticsearch -d
ES基本概念
全文搜索
Full-text Search
全文检索是指计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。 在全文搜索的世界中,存在着几个庞大的帝国,也就是主流工具,主要有:
Apache Lucene
Elasticsearch
Solr
Ferret
倒排索引
Inverted Index
该索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted index)。Elasticsearch能够实现快速、高效的搜索功能,正是基于倒排索引原理。
节点 & 集群
Node & Cluster
Elasticsearch 本质上是一个分布式数据库,允许多台服务器协同工作,每台服务器可以运行多个Elasticsearch实例。单个Elasticsearch实例称为一个节点(Node),一组节点构成一个集群(Cluster)。
索引
Index
Elasticsearch 数据管理的顶层单位就叫做 Index(索引),相当于关系型数据库里的数据库的概念。另外,每个Index的名字必须是小写。
文档
Document
Index里面单条的记录称为 Document(文档)。许多条 Document 构成了一个 Index。Document 使用 JSON 格式表示。同一个 Index 里面的 Document,不要求有相同的结构(scheme),但是最好保持相同,这样有利于提高搜索效率。
类型
Type
Document 可以分组,比如employee这个 Index 里面,可以按部门分组,也可以按职级分组。这种分组就叫做 Type,它是虚拟的逻辑分组,用来过滤 Document,类似关系型数据库中的数据表。 不同的 Type 应该有相似的结构(Schema),性质完全不同的数据(比如 products 和 logs)应该存成两个 Index,而不是一个 Index 里面的两个 Type(虽然可以做到)。
文档元数据
Document metadata
文档元数据为index, _type, _id, 这三者可以唯一表示一个文档,index表示文档在哪存放,type表示文档的对象类别,id为文档的唯一标识。
字段
Fields
每个Document都类似一个JSON结构,它包含了许多字段,每个字段都有其对应的值,多个字段组成了一个 Document,可以类比关系型数据库数据表中的字段。 在 Elasticsearch 中,文档(Document)归属于一种类型(Type),而这些类型存在于索引(Index)中,下图展示了Elasticsearch与传统关系型数据库的类比:
ES索引操作
创建索引
在Postman中,向服务器发送PUT请求:localhost:9200/test1
查询索引
在Postman中,向服务器发送GET请求:localhost:9200/test1
查询所有索引:localhost:9200/_cat/indices?v.
删除索引
在Postman中,向服务器发送DELETE请求:localhost:9200/test1
ES文档操作
添加文档
在Postman中,向服务器发送POST请求:localhost:9200/test1/_doc
_doc/id:在doc后面接id,可以返回自定义的ID
# POST发送json格式数据
{
"name":"张三",
"sex":"男",
"age":30
}
查询文档
在Postman中,向服务器发送GET请求:localhost:9200/test1/_doc/id
修改文档
在Postman中,向服务器发送POST请求:localhost:9200/test1/_doc/id
# POST发送json格式数据
{
"name":"李四",
"sex":"男",
"age":31
}
删除文档
在Postman中,向服务器发送DELETE请求:localhost:9200/test1/_doc/id
条件检索
在Postman中,向服务器发送GET请求:localhost:9200/test1/_search
# GET发送请求体
{
"query":{
"match":{ # match:模糊匹配,math_all:查询所有数据, math_phrease:精确匹配
"name":"李四"
}
}
}
# GET发送分页查询
{
"query":{
"math_all":{
}
},
"from": 0, # from:请求页数
"size": 10 # size:请求的每页数
}
# GET查询指定数据
{
"query":{
"math_all":{
}
},
"from": 0, # from:请求页数
"size":, 10 # size:请求的每页数
"_source": ["name","age"] # _source:指定要查的数据
}
# GET查询指定数据排序
{
"query":{
"math_all":{
}
},
"from": 0, # from:请求页数
"size":, 10 # size:请求的每页数
"_source": ["name","age"], # _source:指定要查的数据
"sort":{ # sort:查询排序
"age":{ # age: 排序的字段
"order":"desc" # order: age字段排序方式
}
}
}
# GET发送请求体 条件组合
{
"query":{
"bool":{
"should":[ # must:同时成立,should:只要一个成立
{
"match":{
"name": "张三"
}
},
{
"match":{
"sex":"男"
}
}
],
"filter":{ # filter:过滤查询
"range":{ # range:范围查询
"age":{ # age:查询的字段名年纪
"gt": 30 # gt:大于30岁
}
}
}
}
}
}
# GET发送请求体 对查询匹配条件高亮显示
{
"query":{
"match":{ # match:模糊匹配,math_all:查询所有数据, math_phrease:精确匹配
"name":"李四"
}
},
"highlight":{ # 对查询结果字段高亮显示
"fields":{
"name":{} # 要高亮显示的字段name
}
}
}
配合maven项目
在maven项目中引入Elasticsearch包
引入依赖
<!-- elasticsearch服务端 -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.8.0</version>
</dependency>
<!-- elasticsearch客户端连接工具 -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.8.0</version>
</dependency>
<!-- JSON 解析器和生成器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
创建连接对象
public static void main(String[] args) {
// 创建ES客户端对象
RestHighLevelClient esClient = new RestHighLevelClient(
// 地址,端口,连接方式
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);
// 关闭ES客户端
try {
esClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
创建索引
public static void main(String[] args) throws Exception {
// 创建ES客户端对象
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);
// 创建索引请求对象
CreateIndexRequest user = new CreateIndexRequest("user");
// 向服务器发送创建索引命令
CreateIndexResponse response = esClient.indices().create(user, RequestOptions.DEFAULT);
// 响应状态
boolean acknowledged = response.isAcknowledged();
System.out.println("索引操作:" + acknowledged);
// 关闭ES客户端
esClient.close();
}
删除索引
public static void main(String[] args) throws Exception{
// 创建ES客户端对象
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);
// 创建索引查询对象
DeleteIndexRequest user1 = new DeleteIndexRequest("user1");
// 向服务器发送查询索引命令
AcknowledgedResponse delete = esClient.indices().delete(user1, RequestOptions.DEFAULT);
// 响应状态
System.out.println(delete.isAcknowledged());
// 关闭ES客户端
esClient.close();
}
插入数据
public static void main(String[] args) throws Exception{
// 创建ES客户端对象
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);
// 插入数据
IndexRequest indexRequest = new IndexRequest();
// 添加到user索引
indexRequest.index("user").id("1001");
User user = new User();
user.setName("王五");
user.setSex("男");
user.setAge(24);
String userJson = JSONObject.toJSONString(user);
indexRequest.source(userJson, XContentType.JSON);
IndexResponse response = esClient.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(response.getResult());
// 关闭ES客户端
esClient.close();
}
修改数据
public static void main(String[] args) throws Exception{
// 创建ES客户端对象
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);
// 修改数据
UpdateRequest request = new UpdateRequest();
request.index("user").id("1001");
request.doc(XContentType.JSON, "sex", "女");
UpdateResponse response = esClient.update(request, RequestOptions.DEFAULT);
System.out.println(response.getResult());
// 关闭ES客户端
esClient.close();
}
查询数据
public static void main(String[] args) throws Exception{
// 创建ES客户端对象
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);
// 查询数据
GetRequest request = new GetRequest();
request.index("user").id("1001");
GetResponse response = esClient.get(request, RequestOptions.DEFAULT);
System.out.println(response.getSourceAsString());
// 关闭ES客户端
esClient.close();
}
删除数据
public static void main(String[] args) throws Exception{
// 创建ES客户端对象
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);
// 查询数据
DeleteRequest request = new DeleteRequest();
request.index("user").id("1001");
DeleteResponse response = esClient.delete(request, RequestOptions.DEFAULT);
System.out.println(response.getResult());
// 关闭ES客户端
esClient.close();
}
批量添加
public static void main(String[] args) throws Exception{
// 创建ES客户端对象
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);
// 批量插入数据
BulkRequest request = new BulkRequest();
request.add(new IndexRequest("user").id("1002").source(XContentType.JSON, "name", "李四"));
request.add(new IndexRequest("user").id("1003").source(XContentType.JSON, "name", "王五"));
request.add(new IndexRequest("user").id("1004").source(XContentType.JSON, "name", "赵六"));
BulkResponse response = esClient.bulk(request, RequestOptions.DEFAULT);
System.out.println(response.getTook());
System.out.println(response.getItems());
// 关闭ES客户端
esClient.close();
}
批量删除
public static void main(String[] args) throws Exception{
// 创建ES客户端对象
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);
// 批量插入数据
BulkRequest request = new BulkRequest();
request.add(new DeleteRequest("user").id("1002"));
request.add(new DeleteRequest("user").id("1003"));
request.add(new DeleteRequest("user").id("1004"));
BulkResponse response = esClient.bulk(request, RequestOptions.DEFAULT);
System.out.println(response.getTook());
System.out.println(response.getItems());
// 关闭ES客户端
esClient.close();
}
条件查询
public static void main(String[] args) throws Exception{
// 创建ES客户端对象
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);
SearchRequest request = new SearchRequest("user");
SearchSourceBuilder builder = new SearchSourceBuilder();
// 全量查询
builder.query(QueryBuilders.matchAllQuery());
// 排序方式
//builder.sort("age", SortOrder.DESC);
// 分页查询
//builder.from(0);
//builder.size(2);
// 排除或保函查询
//String[] exclouds = {"age", "sex"};
//String[] inclouds = {};
//builder.fetchSource(inclouds, exclouds);
// 等值查询
//builder.query(QueryBuilders.termQuery("name", "王五"));
// 模糊查询
//builder.query(QueryBuilders.fuzzyQuery("name", "王五").fuzziness(Fuzziness.ONE));
// 组合查询
//BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// 等于
//boolQuery.must(QueryBuilders.matchQuery("name", "王五"));
// 不等
//boolQuery.should(QueryBuilders.matchQuery("name", "王五"));
//builder.query(boolQuery);
// 聚和查询
// 最大年龄
//AggregationBuilder aggregationBuilder = AggregationBuilders.max("maxAge").field("age");
// 年龄分组
//AggregationBuilder aggregationBuilder = AggregationBuilders.terms("ageGroup").field("age");
//builder.aggregation(aggregationBuilder);
request.source(builder);
SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
System.out.println(hits.getTotalHits());
System.out.println(response.getTook());
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
// 关闭ES客户端
esClient.close();
}