Elasticsearch(二)
elasticSearch安裝,基本操作,入門篇一
1 通過java用戶端對es維護
1.1 工程搭建
- 建立maven工程
- 添加依賴,在pom.xml檔案添加如下依賴:
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>5.6.8</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>5.6.8</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.24</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
- 建立測試類ElasticSearchDemo
1.2 索引操作
1.2.1 建立索引
在測試類中添加testCreateIndex方法:
為友善測試:在測試類中添加before和after方法,分别在測試方法前執行,建立用戶端連接配接對象,測試方法執行後執行,關閉資源
private Client client = null;
@Before
public void before() {
client = new PreBuiltTransportClient(Settings.EMPTY)
.addTransportAddress(new InetSocketTransportAddress(
new InetSocketAddress("localhost", 9300)));
}
@After
public void after() {
client.close();
}
// 建立索引
@Test
public void testCreateIndex() {
client.admin().indices().prepareCreate("blog3").get();
}
1.2.2 删除索引
在測試類中添加testDeleteIndex方法:
//删除索引
@Test
public void testDeleteIndex() {
client.admin().indices().prepareDelete("blog3").get();
}
1.3 建立映射
1.3.1 建立映射前
這裡的映射表示建立索引類型結構,如果不建立映射,Elasticsearch會預設根據建立的文檔中的資料用來建立映射。檢視之前的blog3的映射。
1.3.2 建立映射
在測試類中添加方法:
// 建立映射 注意建立映射時一定要有索引的存在,不然無法建立映射,
// 映射就相當于表結構 建立表和表的結構時,必須要有資料庫(索引)
@Test
public void testCreateMapping1() throws Exception {
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder();
xContentBuilder
.startObject()
.startObject("properties")
.startObject("id")
.field("type", "long")
.endObject()
.startObject("title")
.field("type", "text")
.field("store", false)
.field("analyzer", "ik_smart")
.endObject()
.startObject("content")
.field("type", "text")
.field("store", false)
.field("analyzer", "ik_smart")
.endObject()
.endObject()
.endObject();
PutMappingRequest mappingRequest = Requests.putMappingRequest("blog3").type("article").source(xContentBuilder);
client.admin().indices().putMapping(mappingRequest);
}
1.3.3 建立映射後
建立映射後的結果如下:
1.4 文檔資料操作
1.4.1 建立文檔資料
1.4.1.1 通過XContentBuilder建立
通過XContentBuilder建構文檔資料。在測試中添加方法:
// 建立文檔資料
@Test
public void testCreateDocByXContentBuilder() throws IOException {
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder()
.startObject()
.field("id", 2)
.field("title", "學習路線")
.field("content", "計算機組成原理、計算機網絡、資料結構、作業系統等")
.endObject();
client.prepareIndex("blog3","article","2").setSource(xContentBuilder).get();
}
1.4.1.2 通過POJO建立
通過POJO建構文檔資料。在測試中添加方法:
- 添加Jackson依賴(需要将pojo轉成json對象)
<!--jackson JSON轉換包--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.8.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.8.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.8.1</version> </dependency>
- 建立pojo,在src目錄下建立Article對象
package com.demo;
public class Article {
private Integer id;
private String title;
private String content;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "Article{" +
"id=" + id +
", title='" + title + '\'' +
", content='" + content + '\'' +
'}';
}
}
- 編寫代碼
//根據bean建立文檔資料
@Test
public void testCreateDocByPojo() throws IOException {
Article article = new Article();
article.setId(3);
article.setTitle("elasticSearch");
article.setContent("elasticSearch時搜尋引擎服務,查詢速度快");
ObjectMapper objectMapper = new ObjectMapper();
byte[] source = objectMapper.writeValueAsBytes(article);
client.prepareIndex("blog3","article","3").setSource(source).get();
}
1.4.2 更新文檔資料
1.4.2.1 通過prepareUpdate方法修改
在測試類添加方法:
//根據prepareUpdate更新文檔資料
@Test
public void testUpdateDoc() throws JsonProcessingException {
Article article = new Article();
article.setId(2);
article.setTitle("java學習路線-更新了");
article.setContent("需要學習資料結構、計算機網絡、計算機組成原理、作業系統等-更新了");
ObjectMapper objectMapper = new ObjectMapper();
byte[] sources = objectMapper.writeValueAsBytes(article);
client.prepareUpdate("blog3","article","2").setDoc(sources, XContentType.JSON).get();
}
1.4.2.2 通過update方法修改
添加測試方法:
//根據update更新文檔資料
@Test
public void testUpdate() throws JsonProcessingException, ExecutionException, InterruptedException {
Article article = new Article();
article.setId(3);
article.setTitle("elasticSearch--更新了");
article.setContent("elasticSearch時搜尋引擎服務,查詢速度快--更新了");
ObjectMapper objectMapper = new ObjectMapper();
byte[] bytes = objectMapper.writeValueAsBytes(article);
UpdateRequest request = new UpdateRequest("blog3", "article", "3").doc(bytes,XContentType.JSON);
client.update(request).get();
}
1.4.3 删除文檔資料
//删除文檔
@Test
public void testDelte(){
client.prepareDelete("blog3","article","3").get();
}
1.4.4 批量增加資料
//批量增加資料
@Test
public void testBatchDocs() throws JsonProcessingException, ExecutionException, InterruptedException {
BulkRequestBuilder bulk = client.prepareBulk();
ObjectMapper objectMapper = new ObjectMapper();
for (int i = 1; i <= 10; i++) {
Article article = new Article();
article.setId(i);
article.setTitle("如何學好es"+i);
article.setContent("了解Elasticsearch需要掌握反向索引,版本為:"+i);
byte[] bytes = objectMapper.writeValueAsBytes(article);
IndexRequestBuilder indexRequestBuilder = client.prepareIndex("blog3", "article", String.valueOf(i)).setSource(bytes, XContentType.JSON);
bulk.add(indexRequestBuilder);
}
bulk.execute().get();
}
1.5 查詢
1.5.1 根據字元串查詢
// 根據字元串查詢
@Test
public void testQueryByString() throws Exception {
SearchResponse searchResponse = client.prepareSearch("blog3")
.setTypes("article")
.setQuery(QueryBuilders.queryStringQuery("反向索引"))// 根據字元串查詢
.get();
SearchHits hits = searchResponse.getHits();
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
}
1.5.2 根據詞條查詢
// 根據詞條查詢
/*
* IK分詞器,在建立索引的時候将英文都變成了小寫,這樣友善我們在搜尋的時候可以實作“不區分大小寫”的搜尋,
* 是以在編寫程式時,是以我們在根據英文單詞查詢時,需要将大寫字母轉成小寫字母<toLowerCase()方法>
* */
@Test
public void testQueryByTerm() throws Exception {
SearchResponse searchResponse = client.prepareSearch("blog3")
.setTypes("article")
.setQuery(QueryBuilders.termQuery("content","Elasticsearch".toLowerCase()))//根據詞條查詢
.get();
SearchHits hits = searchResponse.getHits();
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
}
<http://127.0.0.1:9200/_analyze?analyzer=ik_max_word&pretty=true&text=ElasticSearch是一個全文檢索的架構>
1.5.3 結果集處理
在上面的查詢中,擷取到的結果都是json對象,是以我們可以轉成pojo。在測試中添加方法:
//結果集處理
@Test
public void testQueryForResult() throws IOException {
SearchResponse searchResponse = client.prepareSearch("blog3")
.setTypes("article")
.setQuery(QueryBuilders.termQuery("content", "Elasticsearch".toLowerCase()))
.get();
SearchHits hits = searchResponse.getHits();
ArrayList<Article> articles = new ArrayList<>();
ObjectMapper objectMapper = new ObjectMapper();
for (SearchHit hit : hits) {
String source = hit.getSourceAsString();
Article article = objectMapper.readValue(source, Article.class);
articles.add(article);
}
for (Article article : articles) {
System.out.println(article);
}
}
1.5.4 其他查詢實作
@Test
public void testQueryByOtherCondition() throws Exception {
SearchResponse searchResponse = client.prepareSearch("blog3")
.setTypes("article")
//.setQuery(QueryBuilders.queryStringQuery("反向索引"))// 字元串查詢
//.setQuery(QueryBuilders.termQuery("title", "如何"))
//.setQuery(QueryBuilders.termQuery("content","Elasticsearch".toLowerCase()))//根據詞條查詢
//.setQuery(QueryBuilders.matchAllQuery())//查詢所有
//.setQuery(QueryBuilders.wildcardQuery("content","?引"))//比對一個
//.setQuery(QueryBuilders.wildcardQuery("content","*索引"))//零個或者多個
//.setQuery(QueryBuilders.rangeQuery("id").from(1,true).to(5,true))//區間段查詢
.setQuery(QueryBuilders.fuzzyQuery("content","elastiasaarch")) 相似度查詢,比對的錯誤字元個數[0,2]
.get();
SearchHits hits = searchResponse.getHits();
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
}
1.5.5 組合查詢
組合查詢:即添加多個條件。
must(QueryBuilders) : AND,求交集
mustNot(QueryBuilders): NOT,求差集
should(QueryBuilders):OR ,求并集
//組合查詢
@Test
public void testQueryByBoolean(){
SearchResponse searchResponse = client.prepareSearch("blog3")
.setTypes("article")
.setQuery(QueryBuilders
.boolQuery()
.must(QueryBuilders.matchAllQuery())
.mustNot(QueryBuilders.rangeQuery("id")
.from(1, true).to(5, true))).get();
SearchHits hits = searchResponse.getHits();
for (SearchHit hit : hits) {
System.out.println(hit.getSourceAsString());
}
}
1.5.6 使用DSL表達式
使用restful風格程式設計,傳遞消息體,使用head插件檢視索引庫的資訊,進行查詢:
請求體:
{
"query" : {
"bool" : {
"must" : {
"term" : {
"title" : "es"
}
},
"must" : {
"range" : {
"id" : {
"from" : 5,
"to" : 55
}
}
}
}
}
}
1.5.7 分頁并排序
// 分頁并排序
@Test
public void test() throws IOException {
// 調用查詢方法
SearchResponse searchResponse = client.prepareSearch("blog3")
.setTypes("article")
.setQuery(QueryBuilders.matchAllQuery())
.addSort("id", SortOrder.DESC)// 排序
.setFrom(0) // 起始行=(目前頁碼 - 1)* 每頁顯示的條數
.setSize(20) // 每頁顯示的條數
.get();
// 結果集處理
SearchHits hits = searchResponse.getHits();
System.out.println("查詢總數"+hits.getTotalHits());
ObjectMapper objectMapper = new ObjectMapper();
for (SearchHit hit : hits) {
String source = hit.getSourceAsString();
Article article = objectMapper.readValue(source, Article.class);
System.out.println(article);
}
}
1.6 結果高亮顯示
1.6.1 概念
- 高亮:在進行關鍵字搜尋時,搜尋出的内容中的關鍵字會顯示不同的顔色,稱之為高亮。
- 高亮的本質:其始就對檢索到的結果集中包含的關鍵字添加HTML标簽,并且通過相關樣式進行修飾。
例如:
1.6.2 代碼實作
//關鍵字高亮顯示
@Test
public void testQueryByHighLight(){
//設定高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.preTags("<font color='red'>");
highlightBuilder.postTags("</font>");
highlightBuilder.field("title"); // 對哪個字段進行高亮
//查詢
SearchResponse searchResponse = client.prepareSearch("blog3")
.setTypes("article")
.setQuery(QueryBuilders.termQuery("title", "如何"))
.addSort("id", SortOrder.ASC) // 排序
.setFrom(0)// 起始行 = (目前頁碼 - 1) * 每頁顯示的條
.setSize(20)// 每頁顯示的條數
.highlighter(highlightBuilder)// 添加高亮條件
.get();
//結果集處理
SearchHits hits = searchResponse.getHits();
System.out.println(hits.getTotalHits());
for (SearchHit hit : hits) {
HighlightField title = hit.getHighlightFields().get("title");
Text[] fragments = title.getFragments();
if (fragments!=null && fragments.length>0){
System.out.println(fragments[0].toString());
}
}
}
- 效果如下:
2 通過Spring Data對es內建
2.1 Spring Data介紹
Spring Data ElasticSearch 基于 spring data API 簡化 elasticSearch操作,将原始操作elasticSearch的用戶端API 進行封裝,通過ElasticsearchTemplate操作。Spring Data為Elasticsearch項目提供內建搜尋引擎。Spring Data Elasticsearch POJO的關鍵功能區域為中心的模型與Elastichsearch互動文檔和輕松地編寫一個存儲索引庫資料通路層。
2.2 Spring Data Elasticsearch入門
2.2.1 工程搭建
- 建立工程:springdata_elasticSearch
- 添加依賴:
<!--依賴包-->
<dependencies>
<!--ES依賴包-->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>5.6.8</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>5.6.8</version>
</dependency>
<!--日志依賴-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.24</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--測試包-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<!--springdata-es-->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>3.0.7.RELEASE</version>
</dependency>
</dependencies>
2.2.2 增加索引資料
1、建立索引
2、建立映射
3、向索引庫中添加文檔資料
springdata內建es ElasticsearchTemplate
1、建立pojo:
- 添加相關es注解
2、建立dao:需要繼承ElasticsearchRepository
3、編寫service:
4、編寫spring.xml檔案:管理 ElasticsearchTemplate
2.2.2.1 建立pojo
在工程的src目錄下建立Article。
package com.demo.pojo;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
@Document(indexName = "blog4",type = "article")
public class Article {
@Id
private Integer id;
@Field(index = true,store = false,analyzer = "ik_smart",searchAnalyzer = "ik_smart",type = FieldType.Text)
private String title;
@Field(index = true,store = false,analyzer = "ik_smart",searchAnalyzer = "ik_smart",type = FieldType.Text)
private String content;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "Article{" +
"id=" + id +
", title='" + title + '\'' +
", content='" + content + '\'' +
'}';
}
}
注解說明
@Document(indexName=“blob4”,type=“article”): 文檔與pojo映射
indexName:索引的名稱(必填項),type:索引的類型
@Id:主鍵的唯一辨別
@Field(index=true,store=true,analyzer=“ik_smart”,searchAnalyzer=“ik_smart”,type =FieldType.Text)
index:是否設定分詞
store:是否存儲,預設值是false。如果預設設定為false,Elasticsearch預設使用_source存放我們資料内容
analyzer:存儲時使用的分詞器
searchAnalyze:搜尋時使用的分詞器
type: 資料類型
2.2.2.2 編寫dao接口
在工程src目錄下,建立ArticleDao接口,需要繼承ElasticsearchRepository.
package com.demo.dao;
import com.demo.pojo.Article;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface ArticleDao extends ElasticsearchRepository<Article,Integer> {
}
2.2.2.3 編寫service接口以及實作類
- 編寫ArticleService接口
package com.demo.service;
import com.demo.pojo.Article;
public interface ArticleService {
//添加資料
void save(Article article);
}
- 編寫ArticleServiceImpl實作類
package com.demo.service.impl;
import com.demo.dao.ArticleDao;
import com.demo.pojo.Article;
import com.demo.service.ArticleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ArticleServiceImpl implements ArticleService {
@Autowired
private ArticleDao articleDao;
@Override
public void save(Article article) {
articleDao.save(article);
}
}
2.2.2.4 編寫spring.xml檔案
在resources目錄下建立spring.xml檔案:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/data/elasticsearch
http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd">
<!--IoC容器:開啟注解掃描-->
<context:component-scan base-package="com.demo.service"/>
<!--掃描dao-->
<elasticsearch:repositories base-package="com.demo.dao" />
<!--配置es用戶端并且連接配接es服務-->
<elasticsearch:transport-client id="client" cluster-nodes="localhost:9300" cluster-name="elasticsearch" />
<!--ElasticSearch模版對象(底層使用模闆操作,需要用spring建立,并注入client)-->
<bean id="elasticsearchTemplate" class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
<!--注入client-->
<constructor-arg name="client" ref="client"/>
</bean>
</beans>
2.2.2.5 單元測試
在test目錄下建立測試類:
package com.demo;
import com.demo.pojo.Article;
import com.demo.service.ArticleService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@ContextConfiguration(locations = {"classpath:spring.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class EsTemplateDemo {
@Autowired
private ArticleService articleService;
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
// 建立索引和映射
@Test
public void testCreateIndexAndMapping(){
//建立索引
elasticsearchTemplate.createIndex(Article.class);
elasticsearchTemplate.putMapping(Article.class);
}
//測試添加資料
@Test
public void testSave(){
Article article = new Article();
article.setId(1);
article.setTitle("什麼是es");
article.setContent("Elasticsearch是一個全文檢索系統,并且是基于lucene開發");
articleService.save(article);
}
}
2.3 對索引資料維護-CRUD
2.3.1 編寫service接口以及實作類
- 編寫service接口:在接口中添加其他方法
public interface ArticleService {
// 建立索引資料
void save(Article article);
// 批量儲存
void saveAll(List<Article> articles);
// 根據id删除:通過pojo封裝條件
void delete(Article article);
// 根據id删除
void deleteById(Integer id);
// 查詢所有
Iterable<Article> findAll();
// 分頁查詢
Page<Article> findAll(Pageable pageable);
}
- 編寫實作類:實作接口中的相關方法
@Service
public class ArticleServiceImpl implements ArticleService {
@Autowired
private ArticleDao articleDao;
// 儲存索引資料
public void save(Article article) {
articleDao.save(article);
}
// 批量儲存
public void saveAll(List<Article> articles) {
articleDao.saveAll(articles);
}
// 根據id删除:通過pojo封裝條件
public void delete(Article article) {
articleDao.delete(article);
}
// 根據id删除
public void deleteById(Integer id) {
articleDao.deleteById(id);
}
// 查詢所有
public Iterable<Article> findAll() {
return articleDao.findAll();
}
public Page<Article> findAll(Pageable pageable) {
return articleDao.findAll(pageable);
}
}
2.3.2 編寫單元測試
在測試類中添加相關方法:
package com.demo;
import com.demo.pojo.Article;
import com.demo.service.ArticleService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.ArrayList;
import java.util.List;
@ContextConfiguration(locations = {"classpath:spring.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class EsTemplateDemo {
@Autowired
private ArticleService articleService;
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
// 建立索引和映射
@Test
public void testCreateIndexAndMapping(){
//建立索引
elasticsearchTemplate.createIndex(Article.class);
elasticsearchTemplate.putMapping(Article.class);
}
//測試添加資料
@Test
public void testSave(){
Article article = new Article();
article.setId(1);
article.setTitle("什麼是es");
article.setContent("Elasticsearch是一個全文檢索系統,并且是基于lucene開發");
articleService.save(article);
}
//測試批量添加
@Test
public void testSaveAll(){
ArrayList<Article> articles = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
Article article = new Article();
article.setId(i);
article.setTitle("es版本"+i);
article.setContent("spring data elasticsearch可以簡化原生api操作:" + i);
articles.add(article);
}
articleService.saveAll(articles);
}
@Test
public void update(){
Article article = new Article();
article.setId(1);
article.setTitle("es版本更新1");
article.setContent("spring data elasticsearch可以簡化原生api操作更新");
articleService.save(article);
}
//根據id删除
@Test
public void delete(){
Article article = new Article();
article.setId(1);
articleService.delete(article);
}
//根據id删除
@Test
public void deleteById(){
articleService.deleteById(1);
}
//查詢所有
@Test
public void findAll(){
Iterable<Article> articles = articleService.findAll();
articles.forEach(article -> System.out.println(article));
}
//分頁查詢
@Test
public void findByPage(){
//new PageRequest(getPageNumber() + 1, getPageSize(), getSort());
PageRequest pageRequest = new PageRequest(0, 10, Sort.Direction.ASC, "id");
Page<Article> articles = articleService.findByPage(pageRequest);
System.out.println(articles.getTotalPages());//總頁數
System.out.println(articles.getTotalElements());//總條數
List<Article> list = articles.getContent();
for (Article article : list) {
System.out.println(article);
}
}
}
2.4 常用查詢命名規則
關鍵字 | 命名規則 | 解釋 | 示例 |
---|---|---|---|
and | findByField1AndField2 | 根據Field1和Field2獲得資料 | findByTitleAndContent |
or | findByField1OrField2 | 根據Field1或Field2獲得資料 | findByTitleOrContent |
is | findByField | 根據Field獲得資料 | findByTitle |
not | findByFieldNot | 根據Field獲得補集資料 | findByTitleNot |
between | findByFieldBetween | 獲得指定範圍的資料 | findByPriceBetween |
lessThanEqual | findByFieldLessThan | 獲得小于等于指定值的資料 | findByPriceLessThan |
2.4.1 需求
- 根據标題查詢
- 根據标題查詢并且分頁
2.4.2 編寫dao
在dao中添加方法:
public interface ArticleDao extends ElasticsearchRepository<Article, Integer> {
// 根據标題查詢
List<Article> findByTitle(String title);
// 根據标題查詢并且分頁
Page<Article> findByTitle(String title, Pageable pageable);
}
2.4.3 編寫service
- service接口:在接口中添加方法
// 根據标題查詢
List<Article> findByTitle(String title);
// 根據标題查詢并且分頁
Page<Article> findByTitle(String title, Pageable pageable);
- service實作類:實作接口中方法
// 根據标題查詢
public List<Article> findByTitle(String title) {
return articleDao.findByTitle(title);
}
// 根據标題查詢并且分頁
public Page<Article> findByTitle(String title, Pageable pageable) {
return articleDao.findByTitle(title, pageable);
}
2.4.4 單元測試
// 根據标題查詢
@Test
public void testFindByTitle(){
Iterable<Article> articles = articleService.findByTitle("版本");
articles.forEach(article -> System.out.println(article));
}
// 根據标題查詢 并分頁
@Test
public void testFindByTitleAndPage(){
Page<Article> page = articleService.findByTitle("es", (PageRequest.of(0, 10)));
int totalPages = page.getTotalPages();
long totalElements = page.getTotalElements();
System.out.println("總頁數:"+totalPages);
System.out.println("總條數:"+totalElements);
List<Article> articles = page.getContent();
articles.forEach(article -> System.out.println(article));
}
3 搭建ES叢集
3.1 叢集搭建
3.1.1 建立目錄
在磁盤的任意盤符下建立es-cluster目錄,并且在該目錄下建立三個檔案夾,分别為node1,node2以及node3,如圖所示:
3.1.2 複制檔案
将安裝好的es目錄下的相關檔案分别複制到node1\node2\node3目錄下:(删除head插件和曆史資料)
複制後結果如下:
3.1.3 修改配置
- 修改node1節點中的
配置檔案,添加如下配置:node1\config\elasticsearch.yml
#節點1的配置資訊: #叢集名稱,保證唯一 cluster.name: my-elasticsearch #節點名稱,必須不一樣 node.name: node-1 #服務端口号,在同一機器下必須不一樣 http.port: 9200 #叢集間通信端口号,在同一機器下必須不一樣 transport.tcp.port: 9300 #設定叢集自動發現機器ip集合 discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300","127.0.0.1:9301","127.0.0.1:9302"]
- 修改node2節點中的
node2\config\elasticsearch.yml
#節點2的配置資訊: #叢集名稱,保證唯一 cluster.name: my-elasticsearch #節點名稱,必須不一樣 node.name: node-2 #服務端口号,在同一機器下必須不一樣 http.port: 9201 #叢集間通信端口号,在同一機器下必須不一樣 transport.tcp.port: 9301 #設定叢集自動發現機器ip集合 discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300","127.0.0.1:9301","127.0.0.1:9302"]
-
node3\config\elasticsearch.yml
#節點3的配置資訊: #叢集名稱,保證唯一 cluster.name: my-elasticsearch #節點名稱,必須不一樣 node.name: node-3 #服務端口号,在同一機器下必須不一樣 http.port: 9202 #叢集間通信端口号,在同一機器下必須不一樣 transport.tcp.port: 9302 #設定叢集自動發現機器ip集合 discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300","127.0.0.1:9301","127.0.0.1:9302"]
3.1.3 啟動服務
依次啟動3台es服務。
3.2 測試
3.2.1 通過postman測試
- 建立索引和映射
# url
PUT http://localhost:9200/blog1
# 請求體
{
"mappings": {
"article": {
"properties": {
"id": {
"type": "long",
"store": true,
"index":"not_analyzed"
},
"title": {
"type": "text",
"store": true,
"index":"analyzed",
"analyzer":"standard"
},
"content": {
"type": "text",
"store": true,
"index":"analyzed",
"analyzer":"standard"
}
}
}
}
}
- 效果
- 添加文檔
# url
POST localhost:9200/blog1/article/1
# 請求體
{
"id":1,
"title":"ElasticSearch是一個基于Lucene的搜尋伺服器",
"content":"它提供了一個分布式多使用者能力的全文搜尋引擎,基于RESTfulweb接口。Elasticsearch是用Java開發的,并作為Apache許可條款下的開放源碼釋出,是目前流行的企業級搜尋引擎。設計用于雲計算中,能夠時搜尋,穩定,可靠,快速,安裝使用友善。"
}
3.2.2 通過java代碼測試
package com.demo.test;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.Requests;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
//叢集用戶端下建立索引
public class testCreateMappingByCluster {
public static void main(String[] args) throws IOException {
// 1、建立用戶端并且建立連接配接
Map<String, String> map = new HashMap();
map.put("cluster.name", "my-elasticsearch");
InetSocketTransportAddress address1 = new InetSocketTransportAddress(new InetSocketAddress("localhost", 9300));
InetSocketTransportAddress address2 = new InetSocketTransportAddress(new InetSocketAddress("localhost", 9301));
InetSocketTransportAddress address3 = new InetSocketTransportAddress(new InetSocketAddress("localhost", 9302));
Client client = new PreBuiltTransportClient(Settings.builder().put(map).build())
.addTransportAddresses(address1, address2, address3);
// 建立映射
client.admin().indices().prepareCreate("blog2").get();
// 建立索引
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder();
xContentBuilder
.startObject()
.startObject("properties")
.startObject("id")
.field("type", "long")
.endObject()
.startObject("title")
.field("type", "text")
.field("store", false)
.field("analyzer", "ik_smart")
.endObject()
.startObject("content")
.field("type", "text")
.field("store", false)
.field("analyzer", "ik_smart")
.endObject()
.endObject()
.endObject();
PutMappingRequest mappingRequest = Requests.putMappingRequest("blog2").type("article").source(xContentBuilder);
client.admin().indices().putMapping(mappingRequest);
// 3、關閉資源
client.close();
}
}
package com.demo.test;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import java.net.InetAddress;
import java.util.HashMap;
// 建立文檔
public class testCreateDoc {
public static void main(String[] args) throws Exception {
HashMap<String, Object> map = new HashMap<>();
map.put("cluster.name","my-elasticsearch");
Settings settings = Settings.builder().put(map).build();
//建立用戶端通路對象
PreBuiltTransportClient client = new PreBuiltTransportClient(settings);
InetSocketTransportAddress address1 = new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300);
InetSocketTransportAddress address2 = new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301);
InetSocketTransportAddress address3 = new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9302);
client.addTransportAddresses(address1,address2,address3);
// 建立文檔
XContentBuilder builder = XContentFactory.jsonBuilder()
.startObject()
.field("id", 1)
.field("title", "es是什麼")
.field("content", "它是基于Lucene的實作的搜尋伺服器")
.endObject();
// 添加文檔到指定索引庫
client.prepareIndex("blog2","article","1").setSource(builder).get();
client.close();
}
}
3.3 SpringDataElasticsearch配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/data/elasticsearch
http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd
">
<!--包掃描-->
<context:component-scan base-package="com.demo.service" />
<!--掃描Dao包,自動建立執行個體,掃描所有繼承ElasticsearchRepository接口的接口-->
<elasticsearch:repositories base-package="com.demo.dao"/>
<!--配置elasticSearch的連接配接對象Client-->
<elasticsearch:transport-client id="client" cluster-nodes="localhost:9301,localhost:9302,localhost:9303" cluster-name="my-elasticsearch"/>
<!--ElasticSearch模版對象(底層使用模闆操作,需要用spring建立,并注入client)-->
<bean id="elasticsearchTemplate" class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
<constructor-arg name="client" ref="client"></constructor-arg>
</bean>
</beans>