ES相关操作
# ik_smart最少切分
GET _analyze
{
"analyzer": "ik_smart",
"text": "河南科技大学"
}
# ik_max_word 最细粒度划分!穷尽词库所有可能
GET _analyze
{
"analyzer": "ik_max_word",
"text": "河南科技大学"
}
# ===================ES索引相关的基本操作=======================
# 创建索引(数据库)
# 索引库名称:csp ,文档类型名称:mytype ,文档id:1
PUT /csp/mytype/1
{
"name":"兴趣使然的草帽路飞",
"age":"22"
}
# 创建一个csp2索引库:
# 索引库名称:csp2
# 索引库中3个字段:name,age,birthday
# 3个字段的类型为:text,integer,date
PUT /csp2
{
"mappings": {
"properties": {
"name":{
"type": "text"
},
"age":{
"type": "integer"
},
"birthday":{
"type": "date"
}
}
}
}
# 获得索引csp2的相关信息
GET csp2
# 创建索引csp3,文档类型使用默认的_doc,文档id:1
# 数据为:nage,age,birthday
PUT /csp3/_doc/1
{
"name":"兴趣使然的草帽路飞",
"age":22,
"birthday":"1999-01-29"
}
# 查看索引csp3默认的信息
GET csp3
# 查看es健康状态
GET _cat/health
# 查看所有索引库简要信息
GET _cat/indices?v
# 修改索引csp3数据
# 修改的字段name
POST /csp3/_doc/1/_update
{
"doc":{
"name":"海贼王路飞"
}
}
# 删除csp索引库
DELETE csp
# ===================ES文档相关的基本操作=======================
# 创建索引my_index,文档类型user,文档id:1
# user:1
PUT /my_index/user/1
{
"name":"草帽路飞",
"age":22,
"description":"海贼王,我当定了!",
"tags":["吃货","船长","未来的海贼王","橡胶果实能力者"]
}
# user:2
PUT /my_index/user/4
{
"name":"海贼猎人索隆1",
"age":22,
"description":"背后的伤疤,是剑士的耻辱!",
"tags":["路痴","副船长","未来的世界第一大剑豪","三刀流剑客"]
}
PUT /my_index/user/5
{
"name":"海贼猎人索隆2",
"age":25,
"description":"背后的伤疤,是剑士的耻辱!",
"tags":["路痴","副船长","未来的世界第一大剑豪","三刀流剑客"]
}
PUT /my_index/user/2
{
"name":"海贼猎人索隆3",
"age":24,
"description":"背后的伤疤,是剑士的耻辱!",
"tags":["路痴","副船长","未来的世界第一大剑豪","三刀流剑客"]
}
# user:3
PUT /my_index/user/3
{
"name":"黑足山治",
"age":22,
"description":"为了天下女性而活!",
"tags":["色胚","厨师","未来海贼王船上的初始","踢技炫酷"]
}
# 获取数据
# 获取user:1
GET /my_index/user/1
# 搜索数据
GET /my_index/user/_search?q=name:路飞
# 搜索数据,通过json构建查询参数
# 搜索得到的结果中:
# hits: 表示索引和文档相关信息
# "total":
# "value": 查询到的结果的总记录数
# "relation": 搜索结果和搜索参数的关系:eq表示相等 lt小于 gt大于
# "_index": 表示索引名称
# "_tyoe": 表示文档类型
# "_id": 表示文档id
# "_score": 表示搜索结果的权重
# "_source": 表示文档中的数据
# 文档中数据的字段名称以及值
GET /my_index/user/_search
{
"query": {
"match": {
"name": "索隆"
}
}
}
# 搜索数据,通过json构建查询参数,加上结果过滤
# query:构建要搜索的条件,match:构建要匹配的内容
# _source: 结果过滤,只获取name和age字段数据
# sort: 排序条件 age:要排序的字段 order:desc 降序
# from:从第几条数据开始0表示第一条,size:每页显示几条数据
GET /my_index/user/_search
{
"query": {
"match": {
"name": "索隆"
}
},
"_source": ["name","age"],
"sort": [
{
"age": {
"order": "desc"
}
}
],
"from": 0,
"size": 1
}
# 搜索数据:使用bool多条件精确查询
# 查询22岁的所有用户,且名字中带有索隆的
# bool: 多条件精确查询
# must: [] 数组中的所有条件都需要符合 === 且and的关系
GET /my_index/user/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"age": "22"
}
},
{
"match": {
"name": "索隆"
}
}
]
}
}
}
# 搜索数据:使用bool多条件精确查询
# 查询22岁的所有用户,或者名字中带有索隆的所有用户
# bool: 多条件精确查询
# shoud: [] 数组中的所有条件只要有一个符合就行 === 或or的关系
GET /my_index/user/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"age": "22"
}
},
{
"match": {
"name": "索隆"
}
}
]
}
}
}
# 搜索数据:使用bool多条件精确查询,filter过滤
# 查询所有用户,名字中有索隆的,且年龄在22-25之间
# bool: 多条件精确查询,filter:按照字段过滤 === gt lt eq gte大于等于 lte 小于等于
GET /my_index/user/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "索隆"
}
}
],
"filter": {
"range": {
"age": {
"lt": 22,
"gt": 25
}
}
}
}
}
}
# 根据tags数组中的内容搜索,以空格分割查询条件
# 结果:可以得到路飞和山治的信息
GET /my_index/user/_search
{
"query": {
"match": {
"tags": "厨师 船长"
}
}
}
# 精确查询:
# term: 精确查询,直接通过倒排索引指定的词条进行精确查找
# match: 会使用分词器解析(先分析文档,然后再通过分析的文档进行查询)
# 两个类型: text 和 keyword
# 新建一个索引
PUT my_index2
{
"mappings": {
"properties": {
"name":{
"type": "text"
},
"description":{
"type": "keyword"
}
}
}
}
# 向my_index2插入数据
PUT /my_index2/_doc/1
{
"name":"蒙奇D路飞",
"description":"海贼王我当定了!"
}
# 使用分词器查询
# "analyzer": "keyword" 使用ik分词器查询
GET _analyze
{
"analyzer": "keyword",
"text": "海贼王我当定了!"
}
# 使用分词器查询
# "analyzer": "standard" 使用默认分词器查询
# 该分词器会逐个拆分每个词(字)
GET _analyze
{
"analyzer": "standard",
"text": "海贼王我当定了!"
}
# term 精确查询
# 由结果得出:
# keyword类型(description)的字段不会被分词器解析
# text类型(name)的字段会被分词器解析
GET /my_index2/_search
{
"query": {
"term": {
"name": {
"value": "路"
}
}
}
}
# 插入模拟数据
PUT /my_index2/_doc/3
{
"t1":"33",
"t2":"2020-1-17"
}
PUT /my_index2/_doc/4
{
"t1":"44",
"t2":"2020-1-18"
}
PUT /my_index2/_doc/5
{
"t1":"55",
"t2":"2020-1-19"
}
PUT /my_index2/_doc/6
{
"t1":"66",
"t2":"2020-1-20"
}
# 精确查询多个值
GET /my_index2/_search
{
"query": {
"bool": {
"should": [
{
"term": {
"t1": {
"value": "44"
}
}
},
{
"term": {
"t1": {
"value": "55"
}
}
}
]
}
}
}
# (重点)高亮查询:
# highlight:搜索结果高亮展示
# fields:对应的字段数组
# pre_tags: 高亮展示结果的标签前缀,默认是<em>
# post_tags: 高亮展示结果的标签后缀,默认是</em>
GET /my_index/user/_search
{
"query": {
"match": {
"name": "索隆"
}
},
"highlight": {
"pre_tags": "<p class='key' style='color:red'>",
"post_tags": "</p>",
"fields": {
"name":{}
}
}
}
SpringBoot整合ES
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
可以在application.yml中配置,也可以使用下面的方法配置:
ElasticSearchConfig.java
/**
* @Auther: csp1999
* @Date: 2020/07/11/15:16
* @Description: ES 客户端配置
*/
@Configuration // 相当于xml 配置 bean
public class ElasticSearchConfig {
// spring <beans id="restHighLevelClient" class="RestHighLevelClient">
@Bean
public RestHighLevelClient restHighLevelClient(){
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("127.0.0.1", 9200, "http")));
return client;
}
}
SpringBoot测试类
/**
* @Auther: csp1999
* @Date: 2020/07/11/15:16
* @Description: es7.6.x客户端测试 API
*/
@SpringBootTest
class HaustEsApiApplicationTests {
@Autowired
@Qualifier("restHighLevelClient")
private RestHighLevelClient client;
/**
* 索引的创建 Request: PUT csp_index
*
* @throws IOException
*/
@Test
void testCreateIndex() throws IOException {
// 1.创建索引请求
CreateIndexRequest request = new CreateIndexRequest("csp_index");
// 2.执行创建请求 IndicesClient 请求后获得响应
CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
// 输出结果
System.out.println(createIndexResponse);// org.elasticsearch.client.indices.CreateIndexResponse@cd831c72
}
/**
* 获取索引 GET
*
* @throws IOException
*/
@Test
void testExistIndex() throws IOException {
// 1.获取索引库的请求
GetIndexRequest request = new GetIndexRequest("csp_index");
// 2.执行获取索引库的请求
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
// 输出结果
System.out.println(exists);// 如果索引库存在,则输出:true,否则输出false
}
/**
* 删除索引 DELETE
*
* @throws IOException
*/
@Test
void testDeleteIndex() throws IOException {
// 1.删除索引库的请求
DeleteIndexRequest request = new DeleteIndexRequest("csp_index");
// 2.执行删除索引库的请求
AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
// 输出结果
System.out.println(delete.isAcknowledged());// 删除成功输出true,否则为false
}
/**
* 添加文档
*
* @throws IOException
*/
@Test
void testAddDocument() throws IOException {
// 1.创建对象
User user = new User("兴趣使然的草帽路飞", 22);
// 2.创建请求
IndexRequest request = new IndexRequest("csp_index");
// 3.构建请求规则:PUT /csp_index/_doc/1
request.id("1");
request.timeout(TimeValue.timeValueSeconds(1));
//request.timeout("1s");
// 4.将user对象数据放入请求,json 数据: 需要用到fastjson
request.source(JSON.toJSONString(user), XContentType.JSON);
// 5.客户端发送请求,获取响应的结果
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
// 输出结果
// IndexResponse[index=csp_index,type=_doc,id=1,version=1,result=created,seqNo=0,primaryTerm=1,shards={"total":2,"successful":1,"failed":0}]
System.out.println(indexResponse.toString());
System.out.println(indexResponse.status());// CREATED:表示创建成功
}
/**
* 获取文档,判断是否存在
*
* @throws IOException
*/
@Test
void testIsExists() throws IOException {
// 1.判断文档是否存在的请求
GetRequest request = new GetRequest("csp_index", "1");
// 2.执行请求:判断文档是否存在
boolean exists = client.exists(request, RequestOptions.DEFAULT);
// 输出结果
System.out.println(exists);// 存在返回true,否则返回false
}
/**
* 获取文档信息
*
* @throws IOException
*/
@Test
void testGetDocument() throws IOException {
// 1.获取文档信息的请求
GetRequest getRequest = new GetRequest("csp_index", "1");
// 2.执行获取文档信息的请求
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
// 输出结果
System.out.println(getResponse.getSourceAsString()); //{"age":22,"name":"兴趣使然的草帽路飞"}
System.out.println(getResponse);// 返回的全部内容和命令 是一样的:
// {"_index":"csp_index","_type":"_doc","_id":"1","_version":1,"_seq_no":0,"_primary_term":1,"found":true,"_source":{"age":22,"name":"兴趣使然的草帽路飞"}}
}
/**
* 更新文档信息
*
* @throws IOException
*/
@Test
void testUpdateDocument() throws IOException {
// 1.更新文档请求
UpdateRequest updateRequest = new UpdateRequest("csp_index", "1");
// 设置请求超时时间
updateRequest.timeout("1s");
// user数据对象封装到json中
User user = new User("兴趣使然的诺诺亚索隆", 23);
updateRequest.doc(JSON.toJSONString(user), XContentType.JSON);
// 2.执行更新文档请求
UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);
// 输出结果
System.out.println(updateResponse.status());// OK:表示更新成功
}
/**
* 删除文档记录
*
* @throws IOException
*/
@Test
void testDeleteDocument() throws IOException {
// 1.删除文档请求
DeleteRequest deleteRequest = new DeleteRequest("csp_index", "1");
deleteRequest.timeout("1s");
// 2.执行删除文档请求
DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);
// 输出结果
System.out.println(deleteResponse.status());// OK:表示删除成功
}
/**
* 批量插入数据
*
* @throws IOException
*/
@Test
void testBulkRequest() throws IOException {
// 1.批处理请求
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("10s");
// user数据集合
ArrayList<User> list = new ArrayList<>();
list.add(new User("路飞", 1));
list.add(new User("索隆", 2));
list.add(new User("山治", 3));
list.add(new User("娜美", 4));
list.add(new User("罗宾", 5));
list.add(new User("乔巴", 6));
list.add(new User("乌索普", 7));
list.add(new User("弗兰奇", 8));
list.add(new User("布鲁克", 9));
list.add(new User("甚平", 10));
for (int i = 0; i < list.size(); i++) {
// 批量更新,修改,删除 都是在此进行操作
bulkRequest.add(
new IndexRequest("csp_index")
// 批量赋值文档id: 如果不在自己赋值文档id,会默认生成随机的文档id
.id("" + (i + 1))
// ArrayList转换成json
.source(JSON.toJSONString(list.get(i)), XContentType.JSON)
);
}
// 2.执行批量插入请求
BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
// 输出结果
System.out.println(bulkResponse.status());// OK: 表示批量插入成功!
}
/**
* ES中数据搜索:
* SearchRequest 搜索请求
* SearchRequest 搜索请求
* SearchSourceBuilder 条件构造
* HighlightBuilder 构建高亮
* TermQueryBuilder 精确查询
* XXXQueryBuilder 构建我们需要用到的命令
*
* @throws IOException
*/
@Test
void testSearch() throws IOException {
// 1.创建搜索请求
SearchRequest searchRequest = new SearchRequest("csp_index");
// 2.构建搜索条件:条件构造器SearchSourceBuilder
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 高亮结果的条件构造器
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("name");// 要高亮的字段
highlightBuilder.requireFieldMatch(false);// 不需要多个字段高亮,如果需要设置为true
highlightBuilder.preTags("<span style='color:red'>");
highlightBuilder.postTags("</span>");
// 条件构造器,开启搜索结果高亮,并加入高亮结果的条件构造器
sourceBuilder.highlighter(highlightBuilder);
/**
* 查询条件,使用QueryBuilders工具类来实现:
* QueryBuilders.termQuery() 精确查询
* QueryBuilders.matchAllQuery() 匹配所有
*/
//TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "csp");// 精确查询
//MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();// 搜索所有数据
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", "路飞");// 搜索字段name为路飞的数据
// 查询条件(matchQueryBuilder)放入条件构造器
sourceBuilder.query(matchQueryBuilder);
// 条件构造器,开启分页条件: 从第1个数据开始,每页展示5条结果数据
sourceBuilder.from(0);
sourceBuilder.size(5);
// 条件构造器,搜索请求超时时间60s
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
// 将条件构造器放入搜索请求
searchRequest.source(sourceBuilder);
// 执行搜索请求,并获得searchResponse响应
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
// 搜索得到的所有结果都封装在hits里面,拿数据从hits里面获取
SearchHits hits = searchResponse.getHits();
//System.out.println(JSON.toJSONString(hits));
// 遍历hits:解析结果,并将结果放入resultList集合
ArrayList<Map<String, Object>> resultList = new ArrayList<>();
for (SearchHit documentFields : searchResponse.getHits().getHits()) {
// 获取高亮的字段
Map<String, HighlightField> highlightFields = documentFields.getHighlightFields();
HighlightField name = highlightFields.get("name");// 获取高亮的字段
Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();// 先获取原来未高亮的结果
// 解析高亮的字段, 将原来未高亮的title字段换成高亮的字段
if (name != null) {
Text[] fragments = name.fragments();
String newName = "";
for (Text text : fragments) {
newName += text;
}
// 高亮字段替换原来内容
sourceAsMap.put("name", newName);
}
resultList.add(documentFields.getSourceAsMap());
}
// 遍历resultList
resultList.forEach(item -> {
System.out.println(item);// {name=<span style='color:red'>路</span><span style='color:red'>飞</span>, age=1}
});
}
}