java+Elasticsearch搜尋引擎做增刪改查操作(Springboot專案)
Elasticsearch查詢搜尋真的是非常快,所以企業資料量大的一般都儲存到Elasticsearch裡。用來分析,挖掘資料,
Elasticsearch的索引就相當於資料庫,型別,就相當於表,文件就相當於資料庫的row
索引-index
- 一個索引就是一個擁有幾分相似特徵的文件的集合
- 相當於資料庫中的database
型別-type
- 一個型別是你的索引的一個邏輯上的分類/分割槽
- 通常,會為具有一組共同欄位的文件定義一個型別
- 相當於資料庫中的table
文件-document
- 一個文件是一個可被索引的基礎資訊單元
- 文件以JSON(Javascript Object Notation)格式來表示
- 相當於資料庫中的row
分片-shard
- 一個分片是一個 Lucene 的例項,以及它本身就是一個完整的搜尋引擎
- 一個索引可以有多個分片,必須在建立索引的時候指定分片數量,不能動態修改分片數量
- 多個分片主要是為了提高寫入效率
副本-replicas
- 就是分片的副本,副本分片的主要目的就是為了故障轉移
- 主分片的節點掛掉了,一個副本分片就會晉升為主分片的角色
- 在索引寫入時,新文件首先被索引進主分片然後再同步到其它所有的副本分片
- 副本分片可以服務於讀請求,可以通過增加副本的數目來提升查詢效能
廢話少說,先實戰吧
對了,一定要之前下載Elasticsearch,然後啟動,才可以使用哦
首先引入Elasticsearch的依賴包,有很多不同的jar依賴,我目前就選擇了jest客戶端和transport客戶端兩種方式
<dependency> <groupId>io.searchbox</groupId> <artifactId>jest</artifactId> <version>5.3.2</version> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>transport</artifactId> <version>5.5.3</version> </dependency>
配置檔案:
#jest連線方式需要的配置 配置elasticsearch
spring:
elasticsearch:
jest:
uris:
- http://127.0.0.1:9200
read-timeout: 5000
#連線資料來源
datasource:
url: jdbc:oracle:thin:@192.168.0.86:1521:ORCL86
username: exdb_guotu
password: exdb_guotu
driver-class-name: oracle.jdbc.driver.OracleDriver
nitialSize: 5
maxWait: 60000
minIdle: 5
transport連線方式,配置,寫在程式碼裡,不用transport可以不用這段程式碼
package com.config;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.springframework.stereotype.Component;
import java.net.InetAddress;
/**
* Created by df on 2018/9/19.
*/
@Component
public class TransportClientUitl {
private TransportClient transportClient;
//transportClient的載入配置
public TransportClient getClient() throws Exception{
//設定叢集名稱
Settings settings = Settings.builder().put("cluster.name", "df-elaticSearch").build();// 叢集名
//叢集名稱就是我們Elasticsearch的名稱,我的是我自己起的
//建立client
transportClient = new PreBuiltTransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
return transportClient;
}
}
先來個測試,添加個實體,實體裡邊放索引和型別,還有儲存的欄位
package com.entity;
/**
* Created by df on 2018/9/17.
*/
public class entity {
public static final String INDEX_NAME = "df_index";//相當於資料庫名稱
public static final String TYPE = "df_tstype";//相當於表名
private String key;
private String Value;
public entity(){
super();
}
public entity(String key,String Value){
this.key=key;
this.Value=Value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return Value;
}
public void setValue(String value) {
Value = value;
}
}
然後就可以對Elasticsearch做增刪改查了
package com.service;
import com.config.TransportClientUitl;
import com.entity.entity;
import com.sqlSource.SqlHadle;
import io.searchbox.client.JestClient;
import io.searchbox.client.JestResult;
import io.searchbox.core.*;
import io.searchbox.indices.DeleteIndex;
import io.searchbox.indices.mapping.GetMapping;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* Created by df on 2018/9/17.
*/
@Service
public class testServiceImpl implements testService {
private static final Logger LOGGER = LoggerFactory.getLogger(testServiceImpl.class);
@Autowired
private JestClient jestClient;
/**
* 插入單個數據
*/
@Override
public void saveEntity(entity en) {
Index index = new Index.Builder(en)
.index(entity.INDEX_NAME).type(entity.TYPE).build();
try {
jestClient.execute(index);
LOGGER.info("ES 插入完成");
} catch (IOException e) {
e.printStackTrace();
LOGGER.error(e.getMessage());
}
}
SqlHadle sqlHadle = new SqlHadle();
/**
* 批量插入多個
* index 索引名(資料庫名)
* type 型別(表)
*/
@Override
public void insertBatch(String index, String type) {
//從資料庫查詢出來的資料 然後在儲存到Elasticsearch裡
List<Map<String, Object>> entityList = sqlHadle.queryTest();
long startTime = System.currentTimeMillis();
boolean result = false;
try {
//Bulk方式
Bulk.Builder bulk = new Bulk.Builder().defaultIndex(index).defaultType(type);
for (Map map : entityList) {
Index index1 = new Index.Builder(map).build();
bulk.addAction(index1);
}
BulkResult br = jestClient.execute(bulk.build());
result = br.isSucceeded();
} catch (IOException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("批量新增:" + result + " 消耗了" + (endTime - startTime) + "ms");
}
/**
* 查詢某一個欄位
* searchContent 查詢的屬性值
* key 欄位名稱
*/
@Override
public List<entity> searchEntity(String searchContent, String key) {
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchQuery(key, searchContent));
Search search = new Search.Builder(builder.toString()).addIndex(entity.INDEX_NAME)
.addType(entity.TYPE).build();
try {
JestResult result = jestClient.execute(search);
return result.getSourceAsObjectList(entity.class);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 刪除某個id下的文件,想知道id可以去Elasticsearch的共工具裡看,也可以用程式獲取
* id 文件id
* index 索引名(資料庫名)
* type 型別(表)
*/
@Override
public void deleteDoc(String id, String index, String type) {
Delete delete = new Delete.Builder(id).index(index).type(type).build();
JestResult result = null;
try {
result = jestClient.execute(delete);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 刪除某個索引
* index 索引名(資料庫名)
*/
@Override
public void deleteIndex(String index) {
DeleteIndex deleteIndex = new DeleteIndex.Builder(index).build();
JestResult result = null;
try {
result = jestClient.execute(deleteIndex);
System.out.println(result);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 查詢所有 結果Elasticsearch預設只能查出10條,最多的size也只能10000條
* index 索引名(資料庫名)
* type 型別(表)
*/
@Override
public void searchAll(String index, String type) {
GetMapping getMapping = new GetMapping.Builder().addIndex(index)
.addType(type).build();
try {
JestResult jr = jestClient.execute(getMapping);
System.out.println(jr.getJsonString());
} catch (IOException e) {
e.printStackTrace();
}
// SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// sourceBuilder.query(QueryBuilders.matchAllQuery());
// Search search = new Search.Builder(sourceBuilder.toString()).addIndex("df_index").build();
// SearchResult result = null;
// List his = null;
// try {
// result = jestClient.execute(search);
// System.out.println("本次查詢共查到:" + result.getTotal() + "個關鍵字!");
// his = result.getHits(Object.class);
// } catch (IOException e) {
// e.printStackTrace();
// }
// return his;
}
/**
* 全文搜尋 根據某個欄位全篇搜尋
* indexName 索引名(資料庫名)
* typeName 型別(表)
* query 欄位
* query資料是這種格式
* query="{\n" +
" \"from\" : 0,\n" +
" \"size\" : 9999,\n" +
" \"query\" : {\n" +
" \"query_string\" : {\n" +
" \"query\" : \"惠州\"\n" +
" }\n" +
" }\n" +
"}\n";
*/
@Override
public String search(String indexName, String typeName, String query) {
long startTime = System.currentTimeMillis();
Search search = new Search.Builder(query).addIndex(indexName).addType(typeName).build();
JestResult jr = null;
try {
jr = jestClient.execute(search);
long endTime = System.currentTimeMillis();
System.out.println("Elasticsearch中查詢消耗:" + (endTime - startTime) + "ms");
} catch (IOException e) {
e.printStackTrace();
}
return jr.getJsonString();
}
@Autowired
private TransportClientUitl clientUitl;
/**
* 滾動分頁,採用的是TransportClient客戶端方式操作
* 這個滾動分頁其實是查詢索引裡的全部資料,這個效率最高,最快,每一次滾動設定查詢多少頁,
* 然後下一次找到這一次記錄的id然後繼續滾動,直至資料都沒有為止
* 採用條件:資料量大,
* query 查詢需要的配置,如下query變數所示
* indexName 索引名(資料庫名)
* typeName 型別(表)
*/
String query= "\"{\" +\n"+
" \" \\\"query\\\":{\" +\n"+
" \" \\\"match\\\":{\\\"srv_content\\\":\\\"google\\\"}}\" +\n"+
" \" }\" +\n"+
" \"}\"";
public void searchScroll(String query, String indexName, String typeName) {
long startTime = System.currentTimeMillis();
try {
SearchRequestBuilder searchBuilder = clientUitl.getClient().prepareSearch(indexName);
searchBuilder.setTypes(typeName);
//設定每批讀取的的資料量
searchBuilder.setSize(10000);
//預設是查詢所有
searchBuilder.setQuery(QueryBuilders.queryStringQuery("*:*"));
//設定 search context 維護1分鐘的有效期
searchBuilder.setScroll(TimeValue.timeValueMillis(3));
//獲得首次查詢結果
SearchResponse searchResponse = searchBuilder.get();
System.out.println("命中總數量:" + searchResponse.getHits().getTotalHits());
//列印計數
int count = 1;
do {
System.out.println("第" + count + "次列印資料:");
for (SearchHit hit : searchResponse.getHits().getHits()) {
// System.out.println(hit.getSource());
}
count++;
//將scorllId迴圈傳遞
searchResponse=clientUitl.getClient().prepareSearchScroll(searchResponse.getScrollId())
.setScroll(TimeValue.timeValueMillis(1)).execute().actionGet();
//當searchHits的陣列為空的時候結束迴圈,至此資料全部讀取完畢
} while (searchResponse.getHits().getHits().length != 0);
long endTime = System.currentTimeMillis();
System.out.println("Elasticsearch中查詢所有的資料消耗:" + (endTime - startTime) + "ms");
} catch (Exception e) {
e.printStackTrace();
}
}
}
對Elasticsearch做基本的增刪改查就弄好了,附贈兩個Elasticsearch做完操作的圖片