term&terms查询
term查询
term的查询是代表完全匹配,搜索之前不会对你的关键字进行分词,对你的关键字企业文档分词库中去匹配内容。
#term匹配查询
POST /sms_logs_index/sms_logs_type/_search
{
"from": 0, #limit from,size
"size": 5,
"query": {
"term": {
"province": {
"value": "河北"
}
}
}
}
##不会对term中所匹配的值进行分词查询
// java代码实现方式
@Test
public void testQuery() throws IOException {
// 1 创建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 执行查询
RestHighLevelClient client = ESClient.getClient();
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4 获取到_source中的数据
for (SearchHit hit : response.getHits().getHits()) {
Map result = hit.getSourceAsMap();
System.out.println(result);
}
}
terms查询
相当于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查询属于高层查询,它会根据你查询字段类型不一样,采用不同的查询方式
match查询,实际底层就是多个term查询,将多个term查询的结果进行了封装
- 查询的如果是日期或者是数值的话,它会根据你的字符串查询内容转换为日期或者是数值对等
- 如果查询的内容是一个不可被分的内容(keyword),match查询不会对你的查询的关键字进行分词
- 如果查询的内容是一个可被分的内容(text),match则会根据指定的查询内容按照一定的分词规则去分词进行查
match_all查询
查询全部内容,不指定任何查询条件。
POST /sms_logs_index/sms_logs_type/_search
{
"query": {
"match_all": {}
}
}
@Test
public void test_match_all() throws IOException {
// 创建Request ,放入索引和类型
SearchRequest request = new SearchRequest(index);
request.types(type);
builder.size(20); //es默认查询结果只展示10条,这里可以指定展示的条数
//指定查询条件
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery());
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查询
根据某个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匹配的内容,采用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对应一个text
POST /sms_logs_index/sms_logs_type/_search
{
"query": {
"multi_match": {
"query": "河北", #指定text
"fields": ["province","smsContext"] #指定field
}
}
}
// java 实现
@Test
public void test_multi_match() throws IOException {
SearchRequest request = new SearchRequest(index);
request.types(type);
SearchSourceBuilder builder = new SearchSourceBuilder();
// 查询的文本内容 字段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查询
根据多个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查询
前缀查询,可以通过一个关键字去指定一个Field的前缀,从而查询到指定的文档
POST /sms_logs_index/sms_logs_type/_search
{
"query": {
"prefix": {
"smsContext": {
"value": "河"
}
}
}
}
# 与 match查询的不同在于,prefix类似mysql中的模糊查询。而match的查询类似于严格匹配查询
# 针对不可分割词
@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就可以根据输入的内容大概去匹配一下结果,eg.你可以存在一些错别字
#fuzzy查询
POST /sms_logs_index/sms_logs_type/_search
{
"query": {
"fuzzy": {
"corpName": {
"value": "盒马生鲜",
"prefix_length": 2 # 指定前几个字符要严格匹配
}
}
}
}
// 不稳定,查询字段差太多也可能查不到
// java 实现
@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() :指定前几个字符严格匹配
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查询
范围查询,只针对数值类型,对某一个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查询
正则查询,通过你编写的正则表达式去匹配内容
PS: prefix,fuzzy,wildcar和regexp查询效率相对比较低,在对效率要求比较高时,避免去使用
POST /sms_logs_index/sms_logs_type/_search
{
"query": {
"regexp": {
"moible": "109[0-8]{7}" # 匹配的正则规则
}
}
}
//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查询数据的方式: 1 先将用户指定的关键词进行分词处理 2 将分词去词库中进行检索,得到多个文档的id 3 去各个分片中拉去指定的数据 耗时 4 根据数据的得分进行排序 耗时 5 根据from的值,将查询到的数据舍弃一部分 6 返回查询结果 Scroll+size 在ES中查询方式 1 先将用户指定的关键词进行分词处理 2 将分词去词库中进行检索,得到多个文档的id 3 将文档的id存放在一个ES的上下文中,ES内存 4 根据你指定给的size的个数去ES中检索指定个数的数据,拿完数据的文档id,会从上下文中移除 5 如果需要下一页的数据,直接去ES的上下文中,找后续内容 6 循环进行4.5操作
缺点,Scroll是从内存中去拿去数据的,不适合做实时的查询,拿到的数据不是最新的
# 执行scroll查询,返回第一页数据,并且将文档id信息存放在ES的上下文中,指定生存时间
POST /sms_logs_index/sms_logs_type/_search?scroll=1m
{
"query": {
"match_all": {}
},
"size": 2,
"sort": [
{
"fee": {
"order": "desc"
}
}
]
}
#查询下一页的数据
POST /_search/scroll
{
"scroll_id": "DnF1ZXJ5VGhlbkZldGNoAwAAAAAAACSPFnJjV1pHbENVVGZHMmlQbHVZX1JGdmcAAAAAAAAkkBZyY1daR2xDVVRmRzJpUGx1WV9SRnZnAAAAAAAAJJEWcmNXWkdsQ1VUZkcyaVBsdVlfUkZ2Zw==",
"scoll" :"1m" #scorll信息的生存时间
}
#删除scroll在ES中上下文的数据
DELETE /_search/scroll/scrill_id
//java代码
@Test
public void test_query_scroll() throws IOException {
// 1 创建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 获取返回结果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 循环创建SearchScrollRequest
SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
// 6 指定scrollid生存时间
scrollRequest.scroll(TimeValue.timeValueMinutes(1L));
// 7 执行查询获取返回结果
SearchResponse scrollResp = client.scroll(scrollRequest, RequestOptions.DEFAULT);
// 8.判断是否得到数据,输出
if (scrollResp.getHits().getHits() != null && scrollResp.getHits().getHits().length > 0){
System.out.println("=======下一页的数据========");
for (SearchHit hit : scrollResp.getHits().getHits()){
System.out.println(hit.getSourceAsMap());
}
}else{
// 9.判断没有查询到数据-退出循环
System.out.println("没得");
break;
}
}
// 10 创建clearScrollRequest
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
// 11 指定scrollid
clearScrollRequest.addScrollId(scrollId);
// 12 删除
client.clearScroll(clearScrollRequest,RequestOptions.DEFAULT);
}
delete-by-query
根据term,match 等查询方式去删除大量索引
PS:如果你要删除的内容,时index下的大部分数据,推荐创建一个新的index,然后把保留的文档内容,添加到全新的索引
#Delet-by-query 删除
POST /sms-logs-index/sms-logs-type/_delete_by_query
{
"query": {
"range": {
"fee": {
"lt": 20
}
}
}
}
public void deleteByQuery() throws IOException {
// 1.创建DeleteByQueryRequest
DeleteByQueryRequest request = new DeleteByQueryRequest(index);
request.types(type);
// 2.指定条件
request.setQuery(QueryBuilders.rangeQuery("fee").lt(20));
// 3.执行
BulkByScrollResponse response = client.deleteByQuery(request, RequestOptions.DEFAULT);
// 4.输出返回结果
System.out.println(response.toString());
}
复合查询
bool查询
复合过滤器,将你的多个查询条件 以一定的逻辑组合在一起,
- must:所有条件组合在一起,表示 and 的意思
- must_not:将must_not中的条件,全部都不匹配,表示not的意思
- should:所有条件用should 组合在一起,表示or 的意思
# 省是 晋城 或者 北京
# 运营商不能是联通
# smsContent 包含 战士 和 的
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": "战士"
}
},
{
"match": {
"smsContent": "的"
}
}
]
}
}
}
public void boolSearch() throws IOException {
// 1.创建 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","晋城"));
//# 运营商不能是联通
boolQueryBuilder.mustNot(QueryBuilders.termQuery("operatorId",2));
//#smsContent 包含 战士 和的
boolQueryBuilder.must(QueryBuilders.matchQuery("smsContent","战士"));
boolQueryBuilder.must(QueryBuilders.matchQuery("smsContent","的"));
builder.query(boolQueryBuilder);
request.source(builder);
// 3.执行查询
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4.输出结果
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
}
boosting 查询
boosting 查询可以帮助我们去影响查询后的score
- positive:只有匹配上positive 查询的内容,才会被放到返回的结果集中
- negative:如果匹配上了positive 也匹配上了negative, 就可以 降低这样的文档score.
- negative_boost:指定系数,必须小于1 0.5
关于查询时,分数时如何计算的:
- 搜索的关键字再文档中出现的频次越高,分数越高
- 指定的文档内容越短,分数越高。
- 我们再搜索时,指定的关键字也会被分词,这个被分词的内容,被分词库匹配的个数越多,分数就越高。
#boosting 查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"boosting": {
"positive": {
"match": {
"smsContent": "战士"
}
},
"negative": {
"match": {
"smsContent": "团队"
}
},
"negative_boost": 0.2
}
}
}
public void boostSearch() throws IOException {
// 1.创建 searchRequest
SearchRequest request = new SearchRequest(index);
request.types(type);
// 2.指定查询条件
SearchSourceBuilder builder = new SearchSourceBuilder();
BoostingQueryBuilder boost = QueryBuilders.boostingQuery(
QueryBuilders.matchQuery("smsContent", "战士"),
QueryBuilders.matchQuery("smsContent", "团队")
).negativeBoost(0.2f);
builder.query(boost);
request.source(builder);
// 3.执行查询
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4.输出结果
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
}
filter 查询
query 查询:根据你的查询条件,去计算文档的匹配度得到一个分数,并根据分数排序,不会做缓存的。
filter 查询:根据查询条件去查询文档,不去计算分数,而且filter会对经常被过滤的数据进行缓存。
#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.执行
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 4. 输出结果
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
System.out.println(hit.getId()+"的分数是:"+hit.getScore());
}
}
高亮查询
高亮查询就是用户输入的关键字,以一定特殊样式展示给用户,让用户知道为什么这个结果被检索出来
高亮展示的数据,本身就是文档中的一个field,单独将field以highlight的形式返回给用户
ES提供了一个highlight 属性,他和query 同级别。
frament_size: 指定高亮数据展示多少个字符回来
pre_tags:指定前缀标签
post_tags:指定后缀标签
#highlight 高亮查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"match": {
"smsContent": "团队"
}
},
"highlight": {
"fields": {
"smsContent":{}
},
"pre_tags":"",
"post_tags":"",
"fragment_size":10
}
}
public void highLightQuery() throws IOException {
// 1.创建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("")
.postTags("");
builder.highlighter(highlightBuilder);
request.source(builder);
// 3.执行
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//4. 输出结果
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getHighlightFields().get("smsContent"));
}
}
聚合查询
ES的聚合查询和mysql 的聚合查询类似,ES的聚合查询相比mysql 要强大得多。ES提供的统计数据的方式多种多样。
#ES 聚合查询的RSTFul 语法
POST /index/type/_search
{
"aggs":{
"(名字)agg":{
"agg_type":{
"属性":"值"
}
}
}
}
去重计数聚合查询
去重计数,cardinality 先将返回的文档中的一个指定的field进行去重,统计一共有多少条
# 去重计数 查询 province
POST /sms-logs-index/sms-logs-type/_search
{
"aggs": {
"provinceAgg": {
"cardinality": {
"field": "province"
}
}
}
}
public void aggCardinalityC() throws IOException {
// 1.创建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.执行查询
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4.输出返回结果
Cardinality agg = response.getAggregations().get("provinceAgg");
System.out.println(agg.getValue());
}
范围统计
统计一定范围内出现的文档个数,比如,针对某一个field 的值再0100,100200,200~300 之间文档出现的个数分别是多少
范围统计 可以针对 普通的数值,针对时间类型,针对ip类型都可以响应。
数值 rang
时间 date_rang
ip ip_rang
#针对数值方式的范围统计 from 带等于效果 ,to 不带等于效果
POST /sms-logs-index/sms-logs-type/_search
{
"aggs": {
"agg": {
"range": {
"field": "fee",
"ranges": [
{
"to": 30
},
{
"from": 30,
"to": 60
},
{
"from": 60
}
]
}
}
}
}
#时间方式统计
POST /sms-logs-index/sms-logs-type/_search
{
"aggs": {
"agg": {
"date_range": {
"field": "sendDate",
"format": "yyyy",
"ranges": [
{
"to": "2000"
},{
"from": "2000"
}
]
}
}
}
}
#ip 方式 范围统计
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.创建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.执行查询
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4.输出返回结果
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));
}
}
统计聚合
他可以帮你查询指定field 的最大值,最小值,平均值,平方和...
使用 extended_stats
#统计聚合查询 extended_stats
POST /sms-logs-index/sms-logs-type/_search
{
"aggs": {
"agg": {
"extended_stats": {
"field": "fee"
}
}
}
}
// java实现
public void aggExtendedStats() throws IOException {
// 1.创建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.执行查询
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4.输出返回结果
ExtendedStats extendedStats = response.getAggregations().get("agg");
System.out.println("最大值:"+extendedStats.getMaxAsString()+",最小值:"+extendedStats.getMinAsString());
}
其他聚合查询 查看官方文档
https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-metrics-weight-avg-aggregation.html
地图经纬度搜索
#创建一个经纬度索引,指定一个 name ,一个location
PUT /map
{
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1
},
"mappings": {
"map":{
"properties":{
"name":{
"type":"text"
},
"location":{
"type":"geo_point"
}
}
}
}
}
#添加测试数据
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个点确定一个矩形,获取再矩形内的数据
geo_polygon:以多个点,确定一个多边形,获取多边形的全部数据
基于RESTFul 实现地图检索
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 实现 geo_polygon
public class GeoDemo {
RestHighLevelClient client = EsClient.getClient();
String index = "map";
String type="map";
@Test
public void GeoPolygon() throws IOException {
// 1.创建searchRequest
SearchRequest request = new SearchRequest(index);
request.types(type);
// 2.指定 检索方式
SearchSourceBuilder builder = new SearchSourceBuilder();
List 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.执行
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 4.输出结果
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
}
}