說明
- 本博客是繼上篇的擴展,整理介紹操作和官方java API功能,並創建實例java maven項目,記性實際操作。
http操作
接口說明
- 官方接口語法
curl ‐X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' ‐d '<BODY>'
參數 |
解釋 |
VERB |
適當的HTTP方法即:GET、POST、PUT、HEAD、DELTETE |
PROTOCOL |
http或https,當前官方爲http |
HOST |
任意節點的主機名,分佈式安裝也是任意節點 |
PORT |
http服務端口,默認9200 |
PATH |
API的終端路徑,如_count返回集羣中文檔數量 |
QUERY——STRING |
任意可選的查詢字符串參數 |
BODY |
一個JSON格式的請求體,非必須 |
創建索引庫並mapping
- 請求
put http://172.0.0.1:9200/hello
創建hello索引
- 請求體:
- article:type類型;相當於這個索引庫中有張表叫做article下面定義的這張表中的字段的定義,字段默認爲不索引的;
- analyzer:分詞器使用標準分詞器
{
"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"
}
}
}
}
}
創建索引庫再mapping
- 創建索引庫
put http://172.0.0.1:9200/hello2
- 添加mapping
- 請求
PUT http://127.0.0.1:9200/hello2/article/_mapping
- 請求體:
{
"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"
}
}
}
}
刪除索引
- 請求
DELETE http://127.0.0.1:9200/hello2
創建文檔
- 請求
POST http://127.0.0.1:9200/hello/article/1
- 請求體,一般_id和id值相同
{
"id": 1,
"title": "ElasticSearch是一個基於Lucene的搜索服務器",
"content": "它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口。Elasticsearch是用Java開發的,並作爲Apache許可條款下的開放源碼發佈,是當前流行的企業級搜索引擎。設計用於雲計算中,能夠達到實時搜索,穩定,可靠,快速,安裝使用方便。"
}
修改文檔
- 請求
POST http://127.0.0.1:9200/hello/article/1
- 請求體
{
"id": 1,
"title": "第一次修改ElasticSearch是一個基於Lucene的搜索服務器",
"content": "第一次修改它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口。Elasticsearch是用Java開發的,並作爲Apache許可條款下的開放源碼發佈,是當前流行的企業級搜索引擎。設計用於雲計算中,能夠達到實時搜索,穩定,可靠,快速,安裝使用方便。"
}
刪除文檔
- 請求
DELETE http://127.0.0.1:9200/hello/article/2
查看文檔
- 查看文檔有三種方式
- 根據id查看
- 請求
GET http://127.0.0.1:9200/hello/article/1
- 更加關鍵詞查看
- 請求
POST http://127.0.0.1:9200/hello/article/_search
- 請求體
{
"query": {
"term": {
"title": "搜"
}
}
}
- 更加輸入內容分詞再查看
- 請求
POST http://127.0.0.1:9200/hello/article/_search
- 請求體
{
"query": {
"query_string": {
"default_field": "title",
"query": "搜索服務器"
}
}
}
官方java API文檔
- 以下都是我從官方一個個閱讀整理的,全部基於RestHightLevelClient,TransportClient 8版本後刪除。
文檔詳情
java API代碼實現
查詢類說明
- RangeQueryBuilder 範圍查找 gt:大於 lt:小於 gte:大於等於 lte:小於等於
- WildcardQueryBuilder 模糊查詢 使用*表示任意字符
- TermQueryBuilder 精確查詢
- BoolQueryBuilder 布爾類型查詢 用於多條件的拼接(可用使用以下三個方法進行拼接條件)
- must 必須的 文檔必須滿足匹配條件
- must_not 文檔必須不匹配條件
- should 或者 文檔只要滿足一個或多個條件
導包
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.3.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.3.0</version>
</dependency>
java工具類
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.apache.http.HttpHost;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import lombok.extern.slf4j.Slf4j;
@Slf4j //使用了lombok,可以用手動引入private static final Logger log = LoggerFactory.getLogger(ESRestUtil.class);
public final class ESRestUtil {
private RestHighLevelClient client;
public ESRestUtil() {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
//集羣節點
// new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9200, "http")));
this.client = client;
}
/**
* 關閉連接
*/
public void shutdown(){
if(client!=null){
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 創建index
* @param index 創建index
* @param numberShared 分片數
* @param numberReplicas 備份數
* @return
*/
public boolean createIndex(String index,int numberShared,int numberReplicas) {
CreateIndexRequest request = new CreateIndexRequest(index);
//設置分片和備份數
request.settings(Settings.builder()
.put("index.number_of_shards", numberShared)
.put("index.number_of_replicas", numberReplicas)
);
//索引別名
request.alias(new Alias(index+"_alias").filter(QueryBuilders.termQuery("user", "kimchy")));
try {
client.indices().create(request, RequestOptions.DEFAULT);
} catch (IOException e) {
log.error(e.toString(),e);
return false;
}
return true;
}
//TODO 創建索引和規則
/**
* 添加數據和修改
* 文檔地址:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.10/java-rest-high-document-index.html
* @throws IOException
*/
public boolean addDataOrUpload(String index,String id,String jsonString) {
//指定索引
IndexRequest request = new IndexRequest(index);
//指定id
request.id(id);
//添加的數據 文檔
request.source(jsonString, XContentType.JSON);
//同步執行
IndexResponse indexResponse;
try {
indexResponse = client.index(request, RequestOptions.DEFAULT);
} catch (IOException e) {
log.error("添加數據失敗"+e.toString(),e);
return false;
}
if(indexResponse.getResult()==DocWriteResponse.Result.CREATED) {
log.info("First Create");
}else if(indexResponse.getResult() ==DocWriteResponse.Result.UPDATED ) {
log.info("Data Update");
}
return true;
//異步添加
// ActionListener<IndexResponse> listener = new ActionListener<IndexResponse>() {
// @Override
// public void onResponse(IndexResponse indexResponse) {
//
// }
//
// @Override
// public void onFailure(Exception e) {
//
// }
// };
//
// client.indexAsync(request, RequestOptions.DEFAULT, listener);
}
/**
* 獲取指定index和id的 數據
* @param index
* @param id
* @return
*/
public Map<String, Object> getStringById(String index,String id){
log.info("Search Index:{} And Id:{}",index,id);
GetRequest getRequest = new GetRequest(index,id); //index 和id
GetResponse response = null;
try {
response = this.client.get(getRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
//按字段Key獲取對應的值
//DocumentField field = response.getField("content");
//獲取全部的map,除了正常的值之外,會存在key是@version和@timestamp的值
Map<String, Object> source = response.getSource();
log.info("Result Is:"+JsonUtil.toJson(source));
return source;
}
/**
* 根據指定的內容,模糊查詢或精確查詢所有Doc。
* @param content
* @return
*/
public List<Map<String,Object>> getArticle(String index,String key,String content){
// QueryBuilder qb= QueryBuilders.boolQuery().must(QueryBuilders.termQuery("title","JAVA開發工程師")).must(QueryBuilders.termQuery("age",30)) ;
// //精確查詢
QueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(key, content);
// //模糊查詢
// QueryBuilder matchQueryBuilder = QueryBuilders.matchPhraseQuery("content", content);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// sourceBuilder.query(QueryBuilders.termQuery("content", content));
sourceBuilder.query(matchQueryBuilder);
sourceBuilder.from(0);
sourceBuilder.size(10);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(index);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse;
List<Map<String,Object>> list = new ArrayList<>();
try {
searchResponse = this.client.search(searchRequest,RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
for(SearchHit hit:searchHits.getHits()){
System.out.println( hit.getSourceAsString());
list.add(hit.getSourceAsMap());
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
/**
* 模糊查詢
* @param index
* @param key
* @param value
* @return
*/
public SearchHits search(String index,String key,String value){
QueryBuilder matchQueryBuilder = QueryBuilders.matchPhraseQuery(key, value);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// sourceBuilder.query(QueryBuilders.termQuery("content", content));
sourceBuilder.query(matchQueryBuilder);
sourceBuilder.from(0);
sourceBuilder.size(100);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(index);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse;
List<Map<String,Object>> list = new ArrayList<>();
SearchHits searchHits = null;
try {
searchResponse = this.client.search(searchRequest,RequestOptions.DEFAULT);
searchHits = searchResponse.getHits();
for(SearchHit hit:searchHits.getHits()){
System.out.println( hit.getSourceAsString());
list.add(hit.getSourceAsMap());
}
} catch (IOException e) {
e.printStackTrace();
}
return searchHits;
}
/**
* 刪除數據
* @param titleName
* @return
*/
public long deleteArticle(String titleName){
long deleteNum = 0l;
SearchHits searchHits = search("article-2019.08.08.03","title",titleName);
System.out.println("Exxcute Start" );
deleteCommon(searchHits);
//deleteAsync(searchHits);
System.out.println("Exxcute Done" );
return deleteNum;
}
/**
* 刪除數據
* @param index
* @param id
*/
public boolean deleteData(String index,String id) {
DeleteRequest deleteRequest= new DeleteRequest(index,id);
try {
DeleteResponse deleteResponse = this.client.delete(deleteRequest,RequestOptions.DEFAULT);
System.out.println("Delete Done【"+deleteResponse.getId()+"】,Status:【" + deleteResponse.status() + "】");
return true;
} catch (IOException e) {
log.error(e.toString(),e);
}
return false;
}
/**
* 正常刪除
* @param searchHits
*/
private void deleteCommon (SearchHits searchHits){
DeleteRequest deleteRequest = new DeleteRequest();
for(SearchHit hit:searchHits.getHits()) {
deleteRequest = new DeleteRequest("article-2019.08.08.03",hit.getId());
try {
DeleteResponse deleteResponse = this.client.delete(deleteRequest,RequestOptions.DEFAULT);
System.out.println("Delete Done【"+deleteResponse.getId()+"】,Status:【" + deleteResponse.status() + "】");
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 異步刪除
* @param searchHits
*/
@SuppressWarnings("unused")
private void deleteAsync (SearchHits searchHits) {
DeleteRequest deleteRequest = new DeleteRequest();
for(SearchHit hit:searchHits.getHits()){
deleteRequest = new DeleteRequest("article-2019.08.08.03",hit.getId());
//異步刪除
this.client.deleteAsync(deleteRequest, RequestOptions.DEFAULT, new ActionListener<DeleteResponse>() {
@Override
public void onResponse(DeleteResponse deleteResponse) {
RestStatus restStatus = deleteResponse.status();
int status = restStatus.getStatus();
deleteResponse.getId();
System.out.println("Delete Done【"+deleteResponse.getId()+"】,Status:【" + status + "】");
}
@Override
public void onFailure(Exception e) {
e.printStackTrace();
System.out.println("ERROR " + hit.getId());
}
});
}
}
}
總結
- 官方java文檔中,所有API都有兩種形式,同步和異步,系統執行效率要求高的可考慮異步接口,同樣業務流程隨之增大。
- 說點廢話,有用共勉,無用忽略。
- 程序員個人成長,第一步掌握一門編程語言,掌握的標準是,能用該語言完成任何需求,不考慮執行效率。第二步,實現基礎上優化代碼,大幅提升效率。第三步,考慮功能分析和架構、功能設計,評估不同編程語言的特性和技術可控性、擴展性,能爲項目搭建和開發提供有效的技術架構和流程方案。