溫馨提示:電腦端看不到右側目錄的話請減小縮放比例。
API操作—— 新建或刪除查詢索引庫
新建索引庫
新建index,要向服務器發送一個PUT請求,下面是使用curl命令新建了一個名為test的index的例子
curl -XPUT 'localhost:9200/test'
Response:
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "test"
}
刪除索引庫
刪除index,要向服務器發送一個delete請求,下面是刪除上面的test的index的例子
curl -XDELETE 'http://localhost:9200/customer'
Response:
{
"acknowledged": true
}
查詢索引庫
查詢index,要發送一個HEAD請求,例子如下
curl -IHEAD 'localhost:9200/test'
Reponse:
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 359
API操作—— 創建映射關系
接下來的操作用curl比較不方便,復雜的內容使用PostMan進行操作,創建映射關系要使用PUT請求,如下json代碼代表我定義了三個字段,分別是title,url和doc,他們的type屬性即為數據類型,關於elasticsearch的數據類型這里不過多贅述,analyzer為ik_max_word代表使用了ik分詞器的最粗粒度分詞
PUT test/_mapping
{
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word"
},
"url": {
"type": "text"
},
"doc": {
"type": "text",
"analyzer": "ik_max_word"
}
}
}
Reponse:
{
"acknowledged": true
}
API操作—— 查詢映射關系
查詢索引庫的映射關系要使用GET請求,如下我查詢了上面創建的映射關系
curl -XGET 'localhost:9200/test/_mapping'
Response:
{
"test" : {
"mappings" : {
"properties" : {
"doc" : {
"type" : "text",
"analyzer" : "ik_max_word"
},
"title" : {
"type" : "text",
"analyzer" : "ik_max_word"
},
"url" : {
"type" : "text"
}
}
}
}
}
API操作—— 添加更新文檔
添加文檔
添加數據使用GET請求發送json數據,以上面的索引庫為例,我添加以下數據
GET test/_doc
{
"title": "PlumK's blog",
"url": "plumk.site",
"doc": "this is the content,這里是正文"
}
更新文檔
更新數據需要知道數據的id,可以通過查找獲得,其他的跟添加數據差不多,GET請求http://localhost:9200/test/_doc/bm87BW8BcAj1cF19_7Sf
json如下:(這里的bm87BW8BcAj1cF19_7Sf就是我上面插入數據的id)
GET test/_doc/bm87BW8BcAj1cF19_7Sf
{
"title": "PlumK's blog",
"url": "plumk.site",
"doc": "this is the content,這里是修改后的正文"
}
Response:
{
"_index": "test",
"_type": "_doc",
"_id": "bm87BW8BcAj1cF19_7Sf",
"_version": 2,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 1,
"_primary_term": 1
}
API操作—— 刪除文檔
刪除數據同樣需要知道id,以刪除上面的數據為例,對下面url發送DELETE請求:
localhost:9200/test/_doc/bm87BW8BcAj1cF19_7Sf
API操作—— 查詢文檔
Match all查詢
最基本的查詢,他將返回所有結果,每個對象的得分為1
POST /test/_search
{
"query":{
"match_all":{}
}
}
Response:
{
"took": 9,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "test",
"_type": "_doc",
"_id": "bm87BW8BcAj1cF19_7Sf",
"_score": 1.0,
"_source": {
"title": "PlumK's blog",
"url": "plumk.site",
"doc": "this is the content,這里是正文"
}
}
]
}
}
Match查詢
match查詢返回match中屬性相同的條目,下面如果url為plumk就查詢不到了,也就是說必須屬性完全相同
POST test/_search
{
"query": {
"match": {
"url": "plumk.site"
}
}
}
Reponse:
{
"took": 11,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.2876821,
"hits": [
{
"_index": "test",
"_type": "_doc",
"_id": "bm87BW8BcAj1cF19_7Sf",
"_score": 0.2876821,
"_source": {
"title": "PlumK's blog",
"url": "plumk.site",
"doc": "this is the content,這里是修改后的正文"
}
}
]
}
}
Query String查詢
該查詢使用查詢解析器和query_string關鍵字。例如下:
POST test/_search
{
"query": {
"query_string": {
"query": "plumk"
}
}
}
Response:
{
"took": 25,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.2876821,
"hits": [
{
"_index": "test",
"_type": "_doc",
"_id": "bm87BW8BcAj1cF19_7Sf",
"_score": 0.2876821,
"_source": {
"title": "PlumK's blog",
"url": "plumk.site",
"doc": "this is the content,這里是修改后的正文"
}
}
]
}
}
設置最小匹配度查詢
設置minimum_should_match字段,如果滿足這個匹配度就會被查詢出來,不多廢話,看例子
GET test/_search
{
"query": {
"match": {
"title":{"query": "plumk的博客","minimum_should_match": "50%"}
}
}
}
多字段查詢
這里嘗試在url和title中搜索plumk
GET test/_search
{
"query": {
"multi_match": {
"query": "plumk",
"fields": ["url", "title"]
}
}
}
接下來的查詢我接下來可能使用不到,但是考慮到會有同樣剛入門的小白看到這篇博客,所以這里我還是從網上摘抄以下
Term查詢
這些查詢主要處理數字、日期等結構化數據。如下:
POST /schools/_search
{
"query":{
"term":{"zip":"176115"}
}
}
Reponse:
{
"took":1, "timed_out":false, "_shards":{"total":10, "successful":10, "failed":0},
"hits":{
"total":1, "max_score":0.30685282, "hits":[{
"_index":"schools", "_type":"school", "_id":"1", "_score":0.30685282,
"_source":{
"name":"Central School", "description":"CBSE Affiliation",
"street":"Nagan", "city":"paprola", "state":"HP", "zip":"176115",
"location":[31.8955385, 76.8380405], "fees":2200,
"tags":["Senior Secondary", "beautiful campus"], "rating":"3.3"
}
}]
}
}
Range查詢
該查詢用於查找值在值范圍之間的對象。為此,我們需要使用如下運算符
- gte:大於等於
- gt:大於
- lte:小於等於
- lt:小於
POST /schools*/_search
{
"query":{
"range":{
"rating":{
"gte":3.5
}
}
}
}
Response:
{
"took":31, "timed_out":false, "_shards":{"total":10, "successful":10, "failed":0},
"hits":{
"total":3, "max_score":1.0, "hits":[
{
"_index":"schools", "_type":"school", "_id":"2", "_score":1.0,
"_source":{
"name":"Saint Paul School", "description":"ICSE Affiliation",
"street":"Dawarka", "city":"Delhi", "state":"Delhi",
"zip":"110075", "location":[28.5733056, 77.0122136], "fees":5000,
"tags":["Good Faculty", "Great Sports"], "rating":"4.5"
}
},
{
"_index":"schools_gov", "_type":"school", "_id":"2", "_score":1.0,
"_source":{
"name":"Government School", "description":"State Board Affiliation",
"street":"Hinjewadi", "city":"Pune", "state":"MH", "zip":"411057",
"location":[18.599752, 73.6821995] "fees":500,
"tags":["Great Sports"], "rating":"4"
}
},
{
"_index":"schools", "_type":"school", "_id":"3", "_score":1.0,
"_source":{
"name":"Crescent School", "description":"State Board Affiliation",
"street":"Tonk Road", "city":"Jaipur", "state":"RJ", "zip":"176114",
"location":[26.8535922, 75.7923988], "fees":2500,
"tags":["Well equipped labs"], "rating":"4.5"
}
}
]
}
}
復合查詢
這個比較復雜,這里也不過多贅述,可以去看這個博客
此外還有Joining查詢,這個涉及到嵌套映射,就不展開講了,還有地理查詢,暫時用不到,可以去看官方文檔
Java操作——初始化
maven中的pom引用如下:
<dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.5.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.5.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.5.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client-sniffer</artifactId>
<version>7.5.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
java上的elasticsearch可以連接一個或多個主機初始化客戶端,假設我本地主機在9200端口和9021都開了elasticsearch:
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http")));
關閉客戶端:
client.close();
Java 操作——文檔增刪改
添加文檔
首先我們要構建數據,有四種方法,以上面的test索引庫為例:
- 直接提交json字符串,這種比較麻煩:
IndexRequest request = new IndexRequest("test"); //索引
request.id("1"); //id,此項可選,原因前面已經講過了
String jsonString = "{" +
"\"url\":\"rasang.site\"," +
"\"title\":\"rasang's blog\"," +
"\"doc\":\"Welcome to my blog.\"" +
"}";
request.source(jsonString, XContentType.JSON);
- 使用Map作為參數:
Map<String, String> jsonMap = new HashMap<>();
jsonMap.put("url", "rasang.site");
jsonMap.put("title", "rasang's blog");
jsonMap.put("doc", "Welcome to my blog.");
IndexRequest indexRequest = new IndexRequest("test").id("1").source(jsonMap);
- 使用
XConttentBuilder
構建:
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.field("url", "rasang.site");
builder.field("title", "rasang's blog");
builder.field("doc", "Welcome to my blog.");
}
builder.endObject();
IndexRequest indexRequest = new IndexRequest("test")
.id("1").source(builder);
- 使用鍵值構建
IndexRequest indexRequest = new IndexRequest("test")
.id("1")
.source("url", "rasang.site",
"title", "rasang's blog",
"doc", "Welcome to my blog.");
其他可選參數:
request.routing("routing"); //路由值
request.timeout(TimeValue.timeValueSeconds(1)); //設置超時
request.timeout("1s"); ////以字符串形式設置超時時間
request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL); //以WriteRequest.RefreshPolicy實例形式設置刷新策略
request.setRefreshPolicy("wait_for");//以字符串形式刷新策略
request.version(2); //文檔版本
request.versionType(VersionType.EXTERNAL); //文檔類型
request.opType(DocWriteRequest.OpType.CREATE); //操作類型
request.opType("create"); //操作類型 可選create或update
request.setPipeline("pipeline"); //索引文檔之前要執行的攝取管道的名稱
構建完成后發送到elasticsearch執行添加,java的執行方式有兩種
同步執行:
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
同步執行在繼續執行后面的代碼之前會等待返回索引響應,也就是等待執行結果,可能相應失敗或者超時之類的。需要捕獲異常。
異步執行
client.indexAsync(request, RequestOptions.DEFAULT, listener);
異步的方法不會阻塞並立即返回。當執行成功后,使用onResponse的方法回調操作監聽器,如果失敗,則使用onFailure方法回調監聽器。監聽器實例如下:
listener = new ActionListener<IndexResponse>() {
@Override
public void onResponse(IndexResponse indexResponse) {
}
@Override
public void onFailure(Exception e) {
}
};
刪除文檔
刪除文檔需要構建DeleteRequest,下面是刪除一個文檔的例子,同樣的我們也需要文檔的id:
DeleteRequest request = new DeleteRequest("test","u7kkCG8B4ZIWSqMC3kJU");
其他可選參數:
request.routing("routing"); //路由值
request.timeout(TimeValue.timeValueMinutes(2)); //以TimeValue形式設置超時
request.timeout("2m"); //以字符串形式設置超時
request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL); //以WriteRequest.RefreshPolicy實例的形式設置刷新策略
request.setRefreshPolicy("wait_for"); //以字符串的形式設置刷新策略
request.version(2); //版本
request.versionType(VersionType.EXTERNAL); //版本類型
同樣的,刪除請求也可以分同步和異步執行,和上面的創建文檔相同:
同步執行:
DeleteResponse deleteResponse = client.delete(
request, RequestOptions.DEFAULT);
異步執行:
client.deleteAsync(request, RequestOptions.DEFAULT, listener);
修改文檔
修改文檔可以用腳本更新,這里我只記錄用部分文檔更新,因為看起來比較方便,與添加文檔類似的,也有四種方式:
UpdateRequest request = new UpdateRequest("test", id);
String jsonString = "{" +
"\"url\":\"rasang.site\"," +
"\"title\":\"rasang's blog\"" +
"\"doc\":\"this is rasang's blog\"" +
"}";
request.doc(jsonString, XContentType.JSON);
Map<String, String> jsonMap = new HashMap<>();
jsonMap.put("url", "rasang.site");
jsonMap.put("title", "rasang's blog");
jsonMap.put("doc", "this is rasang's blog");
UpdateRequest request = new UpdateRequest("test", id)
.doc(jsonMap);
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.field("url", "rasang.site");
builder.field("title", "rasang's blog");
builder.field("doc", "this is rasang's blog");
}
builder.endObject();
UpdateRequest request = new UpdateRequest("test", id)
.doc(builder);
UpdateRequest request = new UpdateRequest("test", "1")
.doc("url", "rasang.site",
"title", "rasang's blog",
"doc", "this is rasang's blog");
可選參數:
request.routing("routing"); //路由值
request.timeout(TimeValue.timeValueSeconds(1)); //設置超時
request.timeout("1s"); ////以字符串形式設置超時時間
request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL); //以WriteRequest.RefreshPolicy實例形式設置刷新策略
request.setRefreshPolicy("wait_for");//以字符串形式刷新策略
request.retryOnConflict(3); //如果要更新的文檔在更新操作的獲取和索引階段之間被另一個操作更改,重試更新操作的次數
request.fetchSource(true); //啟用源檢索,默認情況下禁用
String[] includes = new String[]{"updated", "r*"};
String[] excludes = Strings.EMPTY_ARRAY;
request.fetchSource(
new FetchSourceContext(true, includes, excludes)); //為特定字段配置源包含
String[] includes = Strings.EMPTY_ARRAY;
String[] excludes = new String[]{"updated"};
request.fetchSource(
new FetchSourceContext(true, includes, excludes)); //為特定字段配置源排除
request.setIfSeqNo(2L); //ifSeqNo
request.setIfPrimaryTerm(1L); //ifPrimaryTerm
request.detectNoop(false); //禁用noop檢測
request.scriptedUpsert(true); //指出無論文檔是否存在,腳本都必須運行,即如果文檔不存在,腳本負責創建文檔。
request.docAsUpsert(true); //指示如果部分文檔尚不存在,則必須將其用作upsert文檔。
request.waitForActiveShards(2); //設置在繼續更新操作之前必須活動的碎片副本數量。
request.waitForActiveShards(ActiveShardCount.ALL); //ActiveShardCount的碎片副本數。可選值:ActiveShardCount.ALL, ActiveShardCount.ONE或者 ActiveShardCount.DEFAULT
同步執行
UpdateResponse updateResponse = client.update(
request, RequestOptions.DEFAULT);
異步執行
client.updateAsync(request, RequestOptions.DEFAULT, listener);
Java 操作——Bulk批量操作
批量操作需要用到Bulk API,下面我將展示批量操作新建文檔,刪除文檔:
BulkRequest request = new BulkRequest();
request.add(new DeleteRequest("test", "3"));
request.add(new UpdateRequest("test", "2")
.doc(XContentType.JSON,"url", "plumk.site"));
request.add(new IndexRequest("posts").id("4")
.source(XContentType.JSON,"field", "baz"));
同步執行
client.bulkAsync(request, RequestOptions.DEFAULT, listener);
異步執行
client.bulkAsync(request, RequestOptions.DEFAULT, listener);
BulkResponse
BulkResponse是執行返回的結果,類似於ArrayList,可以迭代所有操作結果
for (BulkItemResponse e : bulkResponse) {
DocWriteResponse itemResponse = e.getResponse();
switch (bulkItemResponse.getOpType()) {
case INDEX:
case CREATE:
IndexResponse indexResponse = (IndexResponse) itemResponse;
break;
case UPDATE:
UpdateResponse updateResponse = (UpdateResponse) itemResponse;
break;
case DELETE:
DeleteResponse deleteResponse = (DeleteResponse) itemResponse;
}
}
Java 操作——搜索文檔
首先我們要創建SearchRequest對象,指定test索引庫
SearchRequest searchRequest = new SearchRequest("test");
可以指定多個查詢文檔庫,如下:
SearchRequest searchRequest = new SearchRequest("posts2","posts", "posts2", "posts1");
又或者可以這么操作:
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("posts2","posts", "posts2", "posts1");
如果你需要設置路由分片的話:
searchRequest.routing("routing");
指定優先分片查詢:
searchRequest.preference("_local");
然后要添加請求的特征參數,添加特征參數我們需要用到SearchSourceBuilder
對象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
設置查詢的起始索引位置和數量
如下表示從第1條開始,共返回5條文檔數據
sourceBuilder.from(0);
sourceBuilder.size(5);
Match all查詢
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
Multi match查詢
搜索doc或url中含有rasang的文檔
QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery("rasang",
"doc", "url");
WildcardQuery模糊查詢
?匹配單個字符,*匹配多個字符,查詢doc字段含有rasang的文檔
WildcardQueryBuilder queryBuilder = QueryBuilders.wildcardQuery("doc",
"*rasang*");
關鍵字包含查詢
以上查詢doc字段包含blog的文檔
searchSource.query(QueryBuilders.termQuery("doc", "blog"));
// QueryBuilders輸入的詞條會被es解析並進行分詞,在此過程中就已經轉換成全小寫。
matchQuery模糊查詢
QueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("doc", "rasong")
.fuzziness(Fuzziness.AUTO) //啟用模糊查詢
.prefixLength(3)// 在匹配查詢上設置前綴長度選項
.maxExpansions(10);// 設置最大擴展選項以控制查詢的模糊過程
searchSource.query(matchQueryBuilder);
//MatchQueryBuilder輸入的詞條會被es解析並進行分詞,在此過程中就已經轉換成全小寫。
復合查詢
//模糊查詢
WildcardQueryBuilder queryBuilder1 = QueryBuilders.wildcardQuery(
"doc", "*blog*");//搜索doc中含有blog的文檔
WildcardQueryBuilder queryBuilder2 = QueryBuilders.wildcardQuery(
"url", "*rasang*");//搜索url中含有rasang的文檔
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//doc中必須含有blog,url中必須含有rasang,相當於and
boolQueryBuilder.must(queryBuilder1);
boolQueryBuilder.must(queryBuilder2);
還有其他復合如should,mustNot,用法類似。