SpringBoot 整合 ElasticSearch 之 ElasticsearchRepository 的 CRUD、分頁介面
一、前言
這裡寫圖片描述
前面使用了 SpringBoot 整合了 Solr: [增刪改查] SpringBoot 整合 Solr 實現 CRUD、分頁介面、高亮顯示
眼下有一個比 Solr 還火熱的 ElasticSearch,主要是用於大資料、分散式系統中,順便使用 SpringBoot 來整合
Elasticsearch是一個基於Lucene的搜尋伺服器。
它提供了一個分散式多使用者能力的全文搜尋引擎,基於RESTful web介面。Elasticsearch是用Java開發的,並作為Apache許可條款下的開放原始碼釋出,是當前流行的企業級搜尋引擎。設計用於雲端計算中,能夠達到實時搜尋,穩定,可靠,快速,安裝使用方便。
使用的方式主要兩種:
① 一種是經過 SpringData 封裝過的,直接在 dao 介面繼承 ElasticsearchRepository 即可
② 一種是經過 Spring 封裝過的,直接在 Service/Controller 中引入該 bean 即可
@Autowired
ElasticsearchTemplate elasticsearchTemplate;
1
2
二、程式碼
2018.7.14更新,程式碼已經放到 github 上了:https://github.com/larger5/SpringBoot_ElasticSearch_base.git
1、entity
package com.cun.entity;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
/**
* 加上了@Document註解之後,預設情況下這個實體中所有的屬性都會被建立索引、並且分詞
* @author linhongcun
*
*/
//http://120.79.197.131:9200/product
@Document(indexName = "product", type = "book")
public class Book {
@Id
String id;
String name;
String message;
String type;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
2、dao 介面
package com.cun.dao;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import com.cun.entity.Book;
public interface BookDao extends ElasticsearchRepository<Book,String>{
}
1
2
3
4
5
6
7
8
9
10
3、Controller
① ElasticsearchRepository
package com.cun.controller;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.cun.dao.BookDao;
import com.cun.entity.Book;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@RestController
@RequestMapping("/book")
@EnableSwagger2
public class BookController {
@Autowired
private BookDao bookDao;
/**
* 1、查 id
* @param id
* @return
*/
@GetMapping("/get/{id}")
public Book getBookById(@PathVariable String id) {
return bookDao.findOne(id);
}
/**
* 2、查 ++:全文檢索(根據整個實體的所有屬性,可能結果為0個)
* @param q
* @return
*/
@GetMapping("/select/{q}")
public List<Book> testSearch(@PathVariable String q) {
QueryStringQueryBuilder builder = new QueryStringQueryBuilder(q);
Iterable<Book> searchResult = bookDao.search(builder);
Iterator<Book> iterator = searchResult.iterator();
List<Book> list = new ArrayList<Book>();
while (iterator.hasNext()) {
list.add(iterator.next());
}
return list;
}
/**
* 3、查 +++:分頁、分數、分域(結果一個也不少)
* @param page
* @param size
* @param q
* @return
* @return
*/
@GetMapping("/{page}/{size}/{q}")
public List<Book> searchCity(@PathVariable Integer page, @PathVariable Integer size, @PathVariable String q) {
// 分頁引數
Pageable pageable = new PageRequest(page, size);
// 分數,並自動按分排序
FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery()
.add(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("name", q)),
ScoreFunctionBuilders.weightFactorFunction(1000)) // 權重:name 1000分
.add(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("message", q)),
ScoreFunctionBuilders.weightFactorFunction(100)); // 權重:message 100分
// 分數、分頁
SearchQuery searchQuery = new NativeSearchQueryBuilder().withPageable(pageable)
.withQuery(functionScoreQueryBuilder).build();
Page<Book> searchPageResults = bookDao.search(searchQuery);
return searchPageResults.getContent();
}
/**
* 4、增
* @param book
* @return
*/
@PostMapping("/insert")
public Book insertBook(Book book) {
bookDao.save(book);
return book;
}
/**
* 5、刪 id
* @param id
* @return
*/
@DeleteMapping("/delete/{id}")
public Book insertBook(@PathVariable String id) {
Book book = bookDao.findOne(id);
bookDao.delete(id);
return book;
}
/**
* 6、改
* @param book
* @return
*/
@PutMapping("/update")
public Book updateBook(Book book) {
bookDao.save(book);
return book;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
② elasticsearchTemplate(簡單使用)
package com.cun.controller;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 簡單使用 elasticsearchTemplate
* @author linhongcun
*
*/
@RestController
@RequestMapping("/template")
public class BookControllerTemplate {
@Autowired
ElasticsearchTemplate elasticsearchTemplate;
/**
* 查詢所有
* @throws Exception
*/
@GetMapping("/all")
public List<Map<String, Object>> searchAll() throws Exception {
//這一步是最關鍵的
Client client = elasticsearchTemplate.getClient();
// @Document(indexName = "product", type = "book")
SearchRequestBuilder srb = client.prepareSearch("product").setTypes("book");
SearchResponse sr = srb.setQuery(QueryBuilders.matchAllQuery()).execute().actionGet(); // 查詢所有
SearchHits hits = sr.getHits();
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
for (SearchHit hit : hits) {
Map<String, Object> source = hit.getSource();
list.add(source);
System.out.println(hit.getSourceAsString());
}
return list;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
4、yml
server:
context-path: /
port: 80
spring:
data:
elasticsearch:
cluster-name: elasticsearch #預設即為 elasticsearch
cluster-nodes: 120.79.197.131:9300 #配置es節點資訊,逗號分隔,如果沒有指定,則啟動ClientNode
1
2
3
4
5
6
7
8
5、pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
1
2
3
4
三、其他
使用 Swagger 生成介面測試頁面,所有介面均經過測試,完全沒有問題!
<!-- swagger生成介面API -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<!-- 介面API生成html文件 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
這裡寫圖片描述
四、小結
Ⅰ、應用
Github、StackOverFlow 等網站都是使用 ElasticSearch 作為搜尋引擎的
Ⅱ、參考文章:
① springboot整合elasticsearch入門例子
②Spring Boot 整合Elasticsearch
③spring 操作elasticsearch
④ ElasticSearch搜尋例項含高亮顯示及搜尋的特殊字元過濾
⑤ docker環境 快速使用elasticsearch-head外掛
Ⅲ、其他知識須知
9300埠: ES節點之間通訊使用
9200埠: ES節點 和 外部 通訊使用
---------------------