term&terms查詢
term查詢
term的查詢是代表完全匹配,搜索之前不會對你的關(guān)鍵字進行分詞灰瞻,對你的關(guān)鍵字企業(yè)文檔分詞庫中去匹配內(nèi)容。
#term匹配查詢
POST /sms_logs_index/sms_logs_type/_search
{
"from": 0, #limit from,size
"size": 5,
"query": {
"term": {
"province": {
"value": "河北"
}
}
}
}
##不會對term中所匹配的值進行分詞查詢
// java代碼實現(xiàn)方式
@Test
public void testQuery() throws IOException {
// 1 創(chuàng)建Request對象
SearchRequest request = new SearchRequest(index);
request.types(type);
// 2 指定查詢條件
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.from(0);
builder.size(5);
builder.query(QueryBuilders.termQuery("province", "河北"));
request.source(builder);
// 3 執(zhí)行查詢
RestHighLevelClient client = ESClient.getClient();
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4 獲取到_source中的數(shù)據(jù)
for (SearchHit hit : response.getHits().getHits()) {
Map<String, Object> result = hit.getSourceAsMap();
System.out.println(result);
}
}
terms查詢
相當(dāng)于in查詢
terms: where province = 河北 or province = ? or province = ?
#terms 匹配查詢
POST /sms_logs_index/sms_logs_type/_search
{
"from": 0,
"size": 5,
"query": {
"terms": {
"province": [
"河北",
"河南"
]
}
}
}
// java代碼 terms 查詢
@Test
public void test_terms() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.termsQuery("province","河北","河南"));
request.source(builder);
RestHighLevelClient client = ESClient.getClient();
SearchResponse resp = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : resp.getHits().getHits()){
System.out.println(hit);
}
}
match查詢
match查詢屬于高層查詢,它會根據(jù)你查詢字段類型不一樣屏鳍,采用不同的查詢方式
match查詢溉仑,實際底層就是多個term查詢挖函,將多個term查詢的結(jié)果進行了封裝
- 查詢的如果是日期或者是數(shù)值的話,它會根據(jù)你的字符串查詢內(nèi)容轉(zhuǎn)換為日期或者是數(shù)值對等
- 如果查詢的內(nèi)容是一個不可被分的內(nèi)容(keyword)浊竟,match查詢不會對你的查詢的關(guān)鍵字進行分詞
- 如果查詢的內(nèi)容是一個可被分的內(nèi)容(text),match則會根據(jù)指定的查詢內(nèi)容按照一定的分詞規(guī)則去分詞進行查
match_all查詢
查詢?nèi)績?nèi)容怨喘,不指定任何查詢條件津畸。
POST /sms_logs_index/sms_logs_type/_search
{
"query": {
"match_all": {}
}
}
@Test
public void test_match_all() throws IOException {
// 創(chuàng)建Request ,放入索引和類型
SearchRequest request = new SearchRequest(index);
request.types(type);
builder.size(20); //es默認查詢結(jié)果只展示10條,這里可以指定展示的條數(shù)
//指定查詢條件
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery());
request.source(builder);
// 執(zhí)行查詢
RestHighLevelClient client = ESClient.getClient();
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 獲取查詢結(jié)果必怜,遍歷顯示
for (SearchHit hit : response.getHits().getHits()){
System.out.println(hit);
}
}
match查詢
根據(jù)某個Field
POST /sms_logs_index/sms_logs_type/_search
{
"query": {
"match": {
"smsContent": "打車"
}
}
}
@Test
public void test_match_field() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchQuery("smsContext","打車"));
request.source(builder);
RestHighLevelClient client = ESClient.getClient();
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()){
System.out.println(hit);
}
}
布爾match查詢
基于一個Filed匹配的內(nèi)容肉拓,采用and或者or的方式進行連接
# 布爾match查詢
POST /sms_logs_index/sms_logs_type/_search
{
"query": {
"match": {
"smsContext": {
"query": "打車 女士",
"operator": "and" #or
}
}
}
}
@Test
public void test_match_boolean() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchQuery("smsContext","打車 女士").operator(Operator.AND));
request.source(builder);
RestHighLevelClient client = ESClient.getClient();
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()){
System.out.println(hit);
}
}
multi_match查詢
match針對一個field做檢索,multi_match針對多個field進行檢索梳庆,多個key對應(yīng)一個text
POST /sms_logs_index/sms_logs_type/_search
{
"query": {
"multi_match": {
"query": "河北", #指定text
"fields": ["province","smsContext"] #指定field
}
}
}
// java 實現(xiàn)
@Test
public void test_multi_match() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
// 查詢的文本內(nèi)容 字段1 字段2 字段3 暖途。掘剪。堪簿。。看政。
builder.query(QueryBuilders.multiMatchQuery("河北", "province", "smsContext"));
request.source(builder);
RestHighLevelClient client = ESClient.getClient();
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit);
}
}
其他查詢
ID查詢
# id查詢
GET /sms_logs_index/sms_logs_type/1
GET /索引名/type類型/id
public void test_multi_match() throws IOException {
GetRequest request = new GetRequest(index,type,"1");
RestHighLevelClient client = ESClient.getClient();
GetResponse resp = client.get(request, RequestOptions.DEFAULT);
System.out.println(resp.getSourceAsMap());
}
ids查詢
根據(jù)多個id進行查詢更米,類似MySql中的where Id in (id1,id2,id3….)
POST /sms_logs_index/sms_logs_type/_search
{
"query": {
"ids": {
"values": [1,2,3] #id值
}
}
}
//java代碼
@Test
public void test_query_ids() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.idsQuery().addIds("1","2","3"));
request.source(builder);
RestHighLevelClient client = ESClient.getClient();
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()){
System.out.println(hit.getSourceAsMap());
}
}
prefix查詢
前綴查詢欺栗,可以通過一個關(guān)鍵字去指定一個Field的前綴,從而查詢到指定的文檔
POST /sms_logs_index/sms_logs_type/_search
{
"query": {
"prefix": {
"smsContext": {
"value": "河"
}
}
}
}
# 與 match查詢的不同在于征峦,prefix類似mysql中的模糊查詢迟几。而match的查詢類似于嚴(yán)格匹配查詢
# 針對不可分割詞
@Test
public void test_query_prefix() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.prefixQuery("smsContext","河"));
request.source(builder);
RestHighLevelClient client = ESClient.getClient();
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()){
System.out.println(hit.getSourceAsMap());
}
}
fuzzy查詢
fuzzy查詢:模糊查詢,我們可以輸入一個字符的大概栏笆,ES就可以根據(jù)輸入的內(nèi)容大概去匹配一下結(jié)果瘤旨,eg.你可以存在一些錯別字
#fuzzy查詢
POST /sms_logs_index/sms_logs_type/_search
{
"query": {
"fuzzy": {
"corpName": {
"value": "盒馬生鮮",
"prefix_length": 2 # 指定前幾個字符要嚴(yán)格匹配
}
}
}
}
// 不穩(wěn)定,查詢字段差太多也可能查不到
// java 實現(xiàn)
@Test
public void test_query_fuzzy() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.fuzzyQuery("corpName","盒馬生鮮").prefixLength(2));
request.source(builder);
RestHighLevelClient client = ESClient.getClient();
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()){
System.out.println(hit.getSourceAsMap());
}
}
// .prefixLength() :指定前幾個字符嚴(yán)格匹配
wildcard查詢
通配查詢竖伯,與mysql中的like查詢是一樣的存哲,可以在查詢時,在字符串中指定通配符*和占位符七婴?
#wildcard查詢
POST /sms_logs_index/sms_logs_type/_search
{
"query": {
"wildcard": {
"corpName": {
"value": "*車" # 可以使用*和祟偷?指定通配符和占位符
}
}
}
}
# ?代表一個占位符
# ??代表兩個占位符
// java代碼
@Test
public void test_query_wildcard() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.wildcardQuery("corpName","*車"));
request.source(builder);
RestHighLevelClient client = ESClient.getClient();
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()){
System.out.println(hit.getSourceAsMap());
}
}
range查詢
范圍查詢,只針對數(shù)值類型打厘,對某一個Field進行大于或者小于的范圍指定
POST /sms_logs_index/sms_logs_type/_search
{
"query": {
"range": {
"relyTotal": {
"gte": 0,
"lte": 3
}
}
}
}
# 查詢范圍:[gte,lte]
# 查詢范圍:(gt,lt)
//java代碼
@Test
public void test_query_range() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.rangeQuery("fee").lt(5).gt(2));
request.source(builder);
RestHighLevelClient client = ESClient.getClient();
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()){
System.out.println(hit.getSourceAsMap());
}
}
regexp查詢
正則查詢修肠,通過你編寫的正則表達式去匹配內(nèi)容
PS: prefix,fuzzy,wildcar和regexp查詢效率相對比較低,在對效率要求比較高時,避免去使用
POST /sms_logs_index/sms_logs_type/_search
{
"query": {
"regexp": {
"moible": "109[0-8]{7}" # 匹配的正則規(guī)則
}
}
}
//java 代碼
@Test
public void test_query_regexp() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.regexpQuery("moible","106[0-9]{8}"));
request.source(builder);
RestHighLevelClient client = ESClient.getClient();
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()){
System.out.println(hit.getSourceAsMap());
}
}
深分頁Scroll
ES對from+size有限制户盯,from和size兩者之和不能超過1w
原理:
from+size ES查詢數(shù)據(jù)的方式: 1 先將用戶指定的關(guān)鍵詞進行分詞處理 2 將分詞去詞庫中進行檢索嵌施,得到多個文檔的id 3 去各個分片中拉去指定的數(shù)據(jù) 耗時 4 根據(jù)數(shù)據(jù)的得分進行排序 耗時 5 根據(jù)from的值,將查詢到的數(shù)據(jù)舍棄一部分 6 返回查詢結(jié)果 Scroll+size 在ES中查詢方式 1 先將用戶指定的關(guān)鍵詞進行分詞處理 2 將分詞去詞庫中進行檢索莽鸭,得到多個文檔的id 3 將文檔的id存放在一個ES的上下文中吗伤,ES內(nèi)存 4 根據(jù)你指定給的size的個數(shù)去ES中檢索指定個數(shù)的數(shù)據(jù),拿完數(shù)據(jù)的文檔id,會從上下文中移除 5 如果需要下一頁的數(shù)據(jù)硫眨,直接去ES的上下文中足淆,找后續(xù)內(nèi)容 6 循環(huán)進行4.5操作
缺點,Scroll是從內(nèi)存中去拿去數(shù)據(jù)的,不適合做實時的查詢巧号,拿到的數(shù)據(jù)不是最新的
# 執(zhí)行scroll查詢族奢,返回第一頁數(shù)據(jù),并且將文檔id信息存放在ES的上下文中丹鸿,指定生存時間
POST /sms_logs_index/sms_logs_type/_search?scroll=1m
{
"query": {
"match_all": {}
},
"size": 2,
"sort": [
{
"fee": {
"order": "desc"
}
}
]
}
#查詢下一頁的數(shù)據(jù)
POST /_search/scroll
{
"scroll_id": "DnF1ZXJ5VGhlbkZldGNoAwAAAAAAACSPFnJjV1pHbENVVGZHMmlQbHVZX1JGdmcAAAAAAAAkkBZyY1daR2xDVVRmRzJpUGx1WV9SRnZnAAAAAAAAJJEWcmNXWkdsQ1VUZkcyaVBsdVlfUkZ2Zw==",
"scoll" :"1m" #scorll信息的生存時間
}
#刪除scroll在ES中上下文的數(shù)據(jù)
DELETE /_search/scroll/scrill_id
//java代碼
@Test
public void test_query_scroll() throws IOException {
// 1 創(chuàng)建SearchRequest
SearchRequest request = new SearchRequest(index);
request.types(type);
// 2 指定scroll信息,生存時間
request.scroll(TimeValue.timeValueMinutes(1L));
// 3 指定查詢條件
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.size(2);
builder.sort("fee",SortOrder.DESC);
builder.query(QueryBuilders.matchAllQuery());
// 4 獲取返回結(jié)果scrollid ,source
request.source(builder);
RestHighLevelClient client = ESClient.getClient();
SearchResponse response = client.search(request,RequestOptions.DEFAULT);
String scrollId = response.getScrollId();
System.out.println(scrollId);
while(true){
// 5 循環(huán)創(chuàng)建SearchScrollRequest
SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
// 6 指定scrollid生存時間
scrollRequest.scroll(TimeValue.timeValueMinutes(1L));
// 7 執(zhí)行查詢獲取返回結(jié)果
SearchResponse scrollResp = client.scroll(scrollRequest, RequestOptions.DEFAULT);
// 8.判斷是否得到數(shù)據(jù)越走,輸出
if (scrollResp.getHits().getHits() != null && scrollResp.getHits().getHits().length > 0){
System.out.println("=======下一頁的數(shù)據(jù)========");
for (SearchHit hit : scrollResp.getHits().getHits()){
System.out.println(hit.getSourceAsMap());
}
}else{
// 9.判斷沒有查詢到數(shù)據(jù)-退出循環(huán)
System.out.println("沒得");
break;
}
}
// 10 創(chuàng)建clearScrollRequest
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
// 11 指定scrollid
clearScrollRequest.addScrollId(scrollId);
// 12 刪除
client.clearScroll(clearScrollRequest,RequestOptions.DEFAULT);
}
delete-by-query
根據(jù)term,match 等查詢方式去刪除大量索引
PS:如果你要刪除的內(nèi)容,時index下的大部分數(shù)據(jù)靠欢,推薦創(chuàng)建一個新的index,然后把保留的文檔內(nèi)容廊敌,添加到全新的索引
#Delet-by-query 刪除
POST /sms-logs-index/sms-logs-type/_delete_by_query
{
"query": {
"range": {
"fee": {
"lt": 20
}
}
}
}
public void deleteByQuery() throws IOException {
// 1.創(chuàng)建DeleteByQueryRequest
DeleteByQueryRequest request = new DeleteByQueryRequest(index);
request.types(type);
// 2.指定條件
request.setQuery(QueryBuilders.rangeQuery("fee").lt(20));
// 3.執(zhí)行
BulkByScrollResponse response = client.deleteByQuery(request, RequestOptions.DEFAULT);
// 4.輸出返回結(jié)果
System.out.println(response.toString());
}
復(fù)合查詢
bool查詢
復(fù)合過濾器,將你的多個查詢條件 以一定的邏輯組合在一起掺涛,
- must:所有條件組合在一起,表示 and 的意思
- must_not:將must_not中的條件疼进,全部都不匹配薪缆,表示not的意思
- should:所有條件用should 組合在一起,表示or 的意思
# 省是 晉城 或者 北京
# 運營商不能是聯(lián)通
# smsContent 包含 戰(zhàn)士 和 的
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"bool": {
"should": [
{
"term": {
"province": {
"value": "晉城"
}
}
},
{
"term": {
"province": {
"value": "北京"
}
}
}
],
"must_not": [
{
"term": {
"operatorId": {
"value": "2"
}
}
}
],
"must": [
{
"match": {
"smsContent": "戰(zhàn)士"
}
},
{
"match": {
"smsContent": "的"
}
}
]
}
}
}
public void boolSearch() throws IOException {
// 1.創(chuàng)建 searchRequest
SearchRequest request = new SearchRequest(index);
request.types(type);
// 2.指定查詢條件
SearchSourceBuilder builder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
// #省是 晉城 或者北京
boolQueryBuilder.should(QueryBuilders.termQuery("province","北京"));
boolQueryBuilder.should(QueryBuilders.termQuery("province","晉城"));
//# 運營商不能是聯(lián)通
boolQueryBuilder.mustNot(QueryBuilders.termQuery("operatorId",2));
//#smsContent 包含 戰(zhàn)士 和的
boolQueryBuilder.must(QueryBuilders.matchQuery("smsContent","戰(zhàn)士"));
boolQueryBuilder.must(QueryBuilders.matchQuery("smsContent","的"));
builder.query(boolQueryBuilder);
request.source(builder);
// 3.執(zhí)行查詢
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4.輸出結(jié)果
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
}
boosting 查詢
boosting 查詢可以幫助我們?nèi)ビ绊懖樵兒蟮膕core
- positive:只有匹配上positive 查詢的內(nèi)容伞广,才會被放到返回的結(jié)果集中
- negative:如果匹配上了positive 也匹配上了negative, 就可以 降低這樣的文檔score.
- negative_boost:指定系數(shù),必須小于1 0.5
關(guān)于查詢時拣帽,分數(shù)時如何計算的:
- 搜索的關(guān)鍵字再文檔中出現(xiàn)的頻次越高,分數(shù)越高
- 指定的文檔內(nèi)容越短嚼锄,分數(shù)越高减拭。
- 我們再搜索時,指定的關(guān)鍵字也會被分詞区丑,這個被分詞的內(nèi)容拧粪,被分詞庫匹配的個數(shù)越多,分數(shù)就越高沧侥。
#boosting 查詢
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"boosting": {
"positive": {
"match": {
"smsContent": "戰(zhàn)士"
}
},
"negative": {
"match": {
"smsContent": "團隊"
}
},
"negative_boost": 0.2
}
}
}
public void boostSearch() throws IOException {
// 1.創(chuàng)建 searchRequest
SearchRequest request = new SearchRequest(index);
request.types(type);
// 2.指定查詢條件
SearchSourceBuilder builder = new SearchSourceBuilder();
BoostingQueryBuilder boost = QueryBuilders.boostingQuery(
QueryBuilders.matchQuery("smsContent", "戰(zhàn)士"),
QueryBuilders.matchQuery("smsContent", "團隊")
).negativeBoost(0.2f);
builder.query(boost);
request.source(builder);
// 3.執(zhí)行查詢
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4.輸出結(jié)果
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
}
filter 查詢
query 查詢:根據(jù)你的查詢條件可霎,去計算文檔的匹配度得到一個分數(shù),并根據(jù)分數(shù)排序宴杀,不會做緩存的癣朗。
filter 查詢:根據(jù)查詢條件去查詢文檔,不去計算分數(shù)旺罢,而且filter會對經(jīng)常被過濾的數(shù)據(jù)進行緩存旷余。
#filter 查詢
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"corpName": "海爾智家公司"
}
},
{
"range":{
"fee":{
"lte":50
}
}
}
]
}
}
}
public void filter() throws IOException {
// 1.searchRequest
SearchRequest searchRequest = new SearchRequest(index);
searchRequest.types(type);
// 2.指定查詢條件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
boolBuilder.filter(QueryBuilders.termQuery("corpName","海爾智家公司"));
boolBuilder.filter(QueryBuilders.rangeQuery("fee").gt(20));
sourceBuilder.query(boolBuilder);
searchRequest.source(sourceBuilder);
// 3.執(zhí)行
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 4. 輸出結(jié)果
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
System.out.println(hit.getId()+"的分數(shù)是:"+hit.getScore());
}
}
高亮查詢
高亮查詢就是用戶輸入的關(guān)鍵字,以一定特殊樣式展示給用戶扁达,讓用戶知道為什么這個結(jié)果被檢索出來
高亮展示的數(shù)據(jù)正卧,本身就是文檔中的一個field,單獨將field以highlight的形式返回給用戶
ES提供了一個highlight 屬性,他和query 同級別跪解。
frament_size: 指定高亮數(shù)據(jù)展示多少個字符回來
pre_tags:指定前綴標(biāo)簽<front color="red">
post_tags:指定后綴標(biāo)簽 </font>
#highlight 高亮查詢
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"match": {
"smsContent": "團隊"
}
},
"highlight": {
"fields": {
"smsContent":{}
},
"pre_tags":"<font color='red'>",
"post_tags":"</font>",
"fragment_size":10
}
}
public void highLightQuery() throws IOException {
// 1.創(chuàng)建request
SearchRequest request = new SearchRequest(index);
request.types(type);
// 2.指定查詢條件穗酥,指定高亮
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchQuery("smsContent","團隊"));
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("smsContent",10)
.preTags("<font colr='red'>")
.postTags("</font>");
builder.highlighter(highlightBuilder);
request.source(builder);
// 3.執(zhí)行
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//4. 輸出結(jié)果
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getHighlightFields().get("smsContent"));
}
}
聚合查詢
ES的聚合查詢和mysql 的聚合查詢類似,ES的聚合查詢相比mysql 要強大得多。ES提供的統(tǒng)計數(shù)據(jù)的方式多種多樣砾跃。
#ES 聚合查詢的RSTFul 語法
POST /index/type/_search
{
"aggs":{
"(名字)agg":{
"agg_type":{
"屬性":"值"
}
}
}
}
去重計數(shù)聚合查詢
去重計數(shù)骏啰,cardinality 先將返回的文檔中的一個指定的field進行去重,統(tǒng)計一共有多少條
# 去重計數(shù) 查詢 province
POST /sms-logs-index/sms-logs-type/_search
{
"aggs": {
"provinceAgg": {
"cardinality": {
"field": "province"
}
}
}
}
public void aggCardinalityC() throws IOException {
// 1.創(chuàng)建request
SearchRequest request = new SearchRequest(index);
request.types(type);
// 2. 指定使用聚合查詢方式
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.aggregation(AggregationBuilders.cardinality("provinceAgg").field("province"));
request.source(builder);
// 3.執(zhí)行查詢
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4.輸出返回結(jié)果
Cardinality agg = response.getAggregations().get("provinceAgg");
System.out.println(agg.getValue());
}
范圍統(tǒng)計
統(tǒng)計一定范圍內(nèi)出現(xiàn)的文檔個數(shù)抽高,比如判耕,針對某一個field 的值再0100,100200,200~300 之間文檔出現(xiàn)的個數(shù)分別是多少
范圍統(tǒng)計 可以針對 普通的數(shù)值,針對時間類型翘骂,針對ip類型都可以響應(yīng)壁熄。
數(shù)值 rang
時間 date_rang
ip ip_rang
#針對數(shù)值方式的范圍統(tǒng)計 from 帶等于效果 ,to 不帶等于效果
POST /sms-logs-index/sms-logs-type/_search
{
"aggs": {
"agg": {
"range": {
"field": "fee",
"ranges": [
{
"to": 30
},
{
"from": 30,
"to": 60
},
{
"from": 60
}
]
}
}
}
}
#時間方式統(tǒng)計
POST /sms-logs-index/sms-logs-type/_search
{
"aggs": {
"agg": {
"date_range": {
"field": "sendDate",
"format": "yyyy",
"ranges": [
{
"to": "2000"
},{
"from": "2000"
}
]
}
}
}
}
#ip 方式 范圍統(tǒng)計
POST /sms-logs-index/sms-logs-type/_search
{
"aggs": {
"agg": {
"ip_range": {
"field": "ipAddr",
"ranges": [
{
"to": "127.0.0.8"
},
{
"from": "127.0.0.8"
}
]
}
}
}
}
public void aggRang() throws IOException {
// 1.創(chuàng)建request
SearchRequest request = new SearchRequest(index);
request.types(type);
// 2. 指定使用聚合查詢方式
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.aggregation(AggregationBuilders.range("agg").field("fee")
.addUnboundedTo(30)
.addRange(30,60)
.addUnboundedFrom(60));
request.source(builder);
// 3.執(zhí)行查詢
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4.輸出返回結(jié)果
Range agg = response.getAggregations().get("agg");
for (Range.Bucket bucket : agg.getBuckets()) {
String key = bucket.getKeyAsString();
Object from = bucket.getFrom();
Object to = bucket.getTo();
long docCount = bucket.getDocCount();
System.out.println(String.format("key: %s ,from: %s ,to: %s ,docCount: %s",key,from,to,docCount));
}
}
統(tǒng)計聚合
他可以幫你查詢指定field 的最大值碳竟,最小值草丧,平均值,平方和...
使用 extended_stats
#統(tǒng)計聚合查詢 extended_stats
POST /sms-logs-index/sms-logs-type/_search
{
"aggs": {
"agg": {
"extended_stats": {
"field": "fee"
}
}
}
}
// java實現(xiàn)
public void aggExtendedStats() throws IOException {
// 1.創(chuàng)建request
SearchRequest request = new SearchRequest(index);
request.types(type);
// 2. 指定使用聚合查詢方式
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.aggregation(AggregationBuilders.extendedStats("agg").field("fee"));
request.source(builder);
// 3.執(zhí)行查詢
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4.輸出返回結(jié)果
ExtendedStats extendedStats = response.getAggregations().get("agg");
System.out.println("最大值:"+extendedStats.getMaxAsString()+",最小值:"+extendedStats.getMinAsString());
}
其他聚合查詢 查看官方文檔
地圖經(jīng)緯度搜索
#創(chuàng)建一個經(jīng)緯度索引,指定一個 name ,一個location
PUT /map
{
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1
},
"mappings": {
"map":{
"properties":{
"name":{
"type":"text"
},
"location":{
"type":"geo_point"
}
}
}
}
}
#添加測試數(shù)據(jù)
PUT /map/map/1
{
"name":"天安門",
"location":{
"lon": 116.403694,
"lat":39.914492
}
}
PUT /map/map/2
{
"name":"百望山",
"location":{
"lon": 116.26284,
"lat":40.036576
}
}
PUT /map/map/3
{
"name":"北京動物園",
"location":{
"lon": 116.347352,
"lat":39.947468
}
}
ES 的地圖檢索方式
geo_distance :直線距離檢索方式
geo_bounding_box: 以2個點確定一個矩形莹桅,獲取再矩形內(nèi)的數(shù)據(jù)
geo_polygon:以多個點昌执,確定一個多邊形,獲取多邊形的全部數(shù)據(jù)
基于RESTFul 實現(xiàn)地圖檢索
geo_distance
#geo_distance
POST /map/map/_search
{
"query": {
"geo_distance":{
#確定一個點
"location":{
"lon":116.434739,
"lat":39.909843
},
#確定半徑
"distance":20000,
#指定形狀為圓形
"distance_type":"arc"
}
}
}
#geo_bounding_box
POST /map/map/_search
{
"query":{
"geo_bounding_box":{
"location":{
"top_left":{
"lon":116.327805,
"lat":39.95499
},
"bottom_right":{
"lon": 116.363162,
"lat":39.938395
}
}
}
}
}
#geo_polygon
POST /map/map/_search
{
"query":{
"geo_polygon":{
"location":{
# 指定多個點確定 位置
"points":[
{
"lon":116.220296,
"lat":40.075013
},
{
"lon":116.346777,
"lat":40.044751
},
{
"lon":116.236106,
"lat":39.981533
}
]
}
}
}
}
java 實現(xiàn) geo_polygon
public class GeoDemo {
RestHighLevelClient client = EsClient.getClient();
String index = "map";
String type="map";
@Test
public void GeoPolygon() throws IOException {
// 1.創(chuàng)建searchRequest
SearchRequest request = new SearchRequest(index);
request.types(type);
// 2.指定 檢索方式
SearchSourceBuilder builder = new SearchSourceBuilder();
List<GeoPoint> points = new ArrayList<>();
points.add(new GeoPoint(40.075013,116.220296));
points.add(new GeoPoint(40.044751,116.346777));
points.add(new GeoPoint(39.981533,116.236106));
builder.query(QueryBuilders.geoPolygonQuery("location",points));
request.source(builder);
// 3.執(zhí)行
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4.輸出結(jié)果
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
}
}