ElasticSearch基本操作
一、基本介绍
1.1、ES核心概念介绍
初学者建议把es当做数据库学习,es中主要有索引,类型,文档,属性的概念,对应数据库如下:
DB | Elasticsearch |
---|---|
数据库(database) | 索引(indices) |
表(tables) | 类型(types) |
行(rows) | 文档(documents) |
字段(columns) | 属性(fields) |
1.2、分词器介绍
ElasticSeach默认分词器:keyword(精确),standard(拆分)
GET _analyze
{
"analyzer": "keyword",
"text": "我是中国人"
}
GET _analyze
{
"analyzer": "standard",
"text": "我是中国人"
}
ik分词器(需要引入插件):ik_smart (粗粒度)和 ik_max_word(细粒度)
GET _analyze
{
"analyzer": "ik_smart",
"text": "我是中国人"
}
GET _analyze
{
"analyzer": "ik_max_word",
"text": "我是中国人"
}
建议:索引时用ik_max_word尽可能多的分词,而搜索时用ik_smart尽可能提高匹配准度
扩展:自定义分词器词典
**在ik分词器config目录下添加自定义词典,修改配置文件 IKAnalyzer.cfg.xml **
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">yu.dic</entry>
1.3、Rest风格介绍
ES推荐用户使用Restful风格
基本Rest命令说明:
method | url地址 | 描述 |
---|---|---|
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.1、创建索引
PUT test
2.2、创建指定类型索引
es的基本类型有:
- 字符串类型
text 、 keyword - 数值类型
long, integer, short, byte, double, float, half_float, scaled_float - 日期类型
date - 布尔值类型
boolean - 二进制类型
binary
PUT test2
{
"mappings": {
"properties": {
"name":{
"type": "text"
},
"age":{
"type": "long"
},
"birthday":{
"type": "date"
}
}
}
}
2.3、查询索引
GET test
2.4、删除索引
DELETE test
三、文档操作
3.1、创建文档
POST yu/user/1
{
"name":"小张",
"age":3,
"tags":["技术宅","旅游","帅"]
}
POST yu/user/2
{
"name":"张三",
"age":20,
"tags":["技术宅","旅游","帅"]
}
POST yu/user/3
{
"name":"李四",
"age":30,
"tags":["技术宅","旅游","唱歌"]
}
POST yu/user/4
{
"name":"王五",
"age":40,
"tags":["技术宅","旅游","跳舞"]
}
3.2、查询文档
GET yu/user/1
3.3、修改文档
修改一号用户年龄为5岁
#PUT修改
PUT yu/user/1
{
"name":"小张",
"age":5,
"tags":["技术宅","旅游","帅"]
}
#POST修改
POST yu/user/1/_update
{
"doc":{
"age":5
}
}
PUT修改和POST修改区别:PUT会将json数据都进行替换, 而POST只会更新修改字段的值,POST更加灵活,一般推荐POST
3.4、删除文档
DELETE yu/user/1
**扩展: 通过GET _cat/ 可以获得es的当前的很多信息! 通过GET _cat/indices命令 查看elasticsearch 索引情况! **
3.5、复杂查询(重点)
3.5.1 、条件匹配查询
GET yu/user/_search?q=name:张三
#查询一个条件一个值去匹配
GET yu/user/_search
{
"query": {
"match": {
"name": "张三"
}
}
}
#查询一个条件多个值去匹配
GET yu/user/_search
{
"query": {
"match": {
"name": "张三 李四"
}
}
}
3.5.2、自定义查询输出结果
GET yu/user/_search
{
"query": {
"match": {
"name": "张三"
}
},
"_source": ["name", "age"]
}
3.5.3、排序
GET yu/user/_search
{
"query": {
"match": {
"name": "张三"
}
},
"_source": ["name", "age"],
"sort": [
{
"age": {
"order": "asc"
}
}
]
}
3.5.4、分页
GET yu/user/_search
{
"query": {
"match": {
"name": "张三"
}
},
"_source": ["name", "age"],
"sort": [
{
"age": {
"order": "asc"
}
}
],
"from": 0,
"size": 1
}
3.5.4、多条件匹配查询
#and查询,must相当于and
GET yu/user/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "张三"
}
},
{
"match": {
"age": 5
}
}
]
}
}
}
#or查询,should相当于or
GET yu/user/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"name": "张三"
}
},
{
"match": {
"age": 30
}
}
]
}
}
}
#not查询,must_not相当于not
GET yu/user/_search
{
"query": {
"bool": {
"must_not": [
{
"match": {
"age": 30
}
}
]
}
}
}
3.5.5、过滤查询
GET yu/user/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "张三"
}
}
],
"filter": [
{
"range": {
"age": {
"gte": 10,
"lte": 20
}
}
}
]
}
}
}
3.5.6、精确查询(term)
term 查询是直接通过倒排索引指定的词条进程精确查找的 !
text类型会被拆分,而keyword类型不会
准备数据
#创建索引
PUT termdb
{
"mappings": {
"properties": {
"name":{
"type":"keyword"
},
"birth":{
"type": "text"
}
}
}
}
#创建文档
PUT termdb/_doc/1
{
"name":"小张",
"birth":"1997-09-14"
}
#创建文档
PUT termdb/_doc/2
{
"name":"张三",
"birth":"1997-10-15"
}
查询
#查询keyword类型的:只会查出来一条
GET termdb/_doc/_search
{
"query":{
"term": {
"name": "张三"
}
}
}
#查询text类型的:会查出来多条
GET termdb/_doc/_search
{
"query":{
"term": {
"birth": "1997"
}
}
}
注意:当用term查询一个text类型时,term无法对其精确匹配的 ,查询条件缩小(值为:张三,查询条件:张)会分词查询
3.5.7、高亮查询
GET yu/user/_search
{
"query":{
"match": {
"name": "张三"
}
},
"highlight": {
"fields": {
"name":{}
}
}
}
定制高亮属性
GET yu/user/_search
{
"query":{
"match": {
"name": "张三"
}
},
"highlight":{
"pre_tags": "<p style='color:red'>",
"post_tags": "</p>",
"fields": {
"name": {}
}
}
}
四、Springboot整合ElasticSearch
可参考elasticSearch官网:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html
4.1、添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
若es本地版本和springboot默认es版本不一致,需要自定义版本
<properties>
<!--自定义elasticSearch版本-->
<elasticsearch.version>7.12.0</elasticsearch.version>
</properties>
4.2、注册RestHighLevelClient 对象
@Configuration
public class ElasticSearchConfig {
@Bean
public RestHighLevelClient restHighLevelClient() {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http")));
return client;
}
}
4.3、RestHighLevelClient对象操作索引
先注入RestHighLevelClient对象
@Autowired
RestHighLevelClient restHighLevelClient;
4.3.1、创建索引
@Test
void createIndices() throws IOException {
//创建索引请求
CreateIndexRequest createIndexRequest = new CreateIndexRequest("java_indices");
//客户端执行请求
CreateIndexResponse response = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
System.out.println(response);
}
4.3.2、查询索引
//判断索引是否存在
@Test
void isExistIndices() throws IOException {
GetIndexRequest getIndexRequest = new GetIndexRequest("java_indices");
boolean exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
System.out.println(exists);
}
4.3.3、删除索引
@Test
void deleteIndices() throws IOException {
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("java_indices");
AcknowledgedResponse acknowledgedResponse = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
System.out.println(acknowledgedResponse.isAcknowledged());
}
4.4、RestHighLevelClient对象操作文档
4.4.1、创建文档
@Test
void createDocument() throws IOException {
//创建请求并指定索引
IndexRequest request = new IndexRequest("java_indices");
request.id("1"); // 设置ID
request.timeout("1s"); // 设置超时时间
request.source(JSON.toJSONString(new User("张三", 20)), XContentType.JSON); //设置数据
//客户端发送请求
IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
System.out.println(response.toString());
}
4.4.2、查询文档
//根据ID获取指定索引的文档信息,判断是否存在
@Test
void getDocument() throws IOException {
GetRequest request = new GetRequest("java_indices", "1");
//request.id("1");
//判断指定的索引和id是否存在
boolean exists = restHighLevelClient.exists(request, RequestOptions.DEFAULT);
System.out.println(exists);
//获取指定的id信息
GetResponse response = restHighLevelClient.get(request, RequestOptions.DEFAULT);
System.out.println(response.getSourceAsString());
//System.out.println(response.isExists());
}
4.4.3、更新文档
//更新文档(Update),重新插入同一个id的数据也是更新(PUT操作)
@Test
void updateDocument() throws IOException {
UpdateRequest request = new UpdateRequest("java_indices", "1");
request.timeout("1s");
//封装需要更新的文档信息
request.doc(JSON.toJSONString(new User("小张", 10)), XContentType.JSON);
UpdateResponse response = restHighLevelClient.update(request, RequestOptions.DEFAULT);
System.out.println(response.getResult());
}
4.4.4、删除文档
@Test
void deleteDocument() throws IOException {
DeleteRequest request = new DeleteRequest("java_indices", "1");
request.timeout("1s");
DeleteResponse response = restHighLevelClient.delete(request, RequestOptions.DEFAULT);
System.out.println(response.getResult());
}
4.4.5、批量插入文档
@Test
void batchCreateDocument() throws IOException {
//创建批量的请求
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("10s");
List<User> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
User user = new User("张三" + i, 20 + i);
list.add(user);
}
//遍历list,把多条数据放到BulkRequest中
for (int i = 0; i < list.size(); i++) {
IndexRequest indexRequest = new IndexRequest("java_indices");
indexRequest.id("" + i);
indexRequest.source(JSON.toJSONString(list.get(i)), XContentType.JSON);
bulkRequest.add(indexRequest);
}
//客户端执行批量操作
BulkResponse responses = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
System.out.println(responses.hasFailures()); //是否失败,如果false则表示全部成功
}
4.4.6、文档复杂查询和高亮
@Test
void searchDocument() throws IOException {
//创建批量搜索请求
SearchRequest request = new SearchRequest("java_indices");
//构建搜索条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//查询条件,可以通过 QueryBuilders 工具来实现
//当中文查询时,如果使用ik分词器会查询不到数据,属性需要使用xxx.keyword才能查询到数据
//TermQueryBuilder termQuery = QueryBuilders.termQuery("name.keyword", "张三1");//精确查询
MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("name", "张三"); //模糊查询
//BoolQueryBuilder boolQuery = QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("name", "张三")); //多条件查询
searchSourceBuilder.query(matchQuery); //查询
searchSourceBuilder.sort("age", SortOrder.ASC); //排序
searchSourceBuilder.from(0); //分页起始
searchSourceBuilder.size(5); //分页一页显示的数量
searchSourceBuilder.timeout(TimeValue.timeValueSeconds(1)); //设置超时时间
//创建高亮生成器
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("name");
highlightBuilder.preTags("<p style='color:red'>");
highlightBuilder.postTags("</p>");
//设置高亮
searchSourceBuilder.highlighter(highlightBuilder);
//将查询条件放入搜索请求request中
request.source(searchSourceBuilder);
//客户端执行请求
SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(response.getHits()));
//遍历Hits
for (SearchHit hit : response.getHits()) {
System.out.println(hit.getSourceAsMap());
}
}