共计 6494 个字符,预计需要花费 17 分钟才能阅读完成。
一、需要
在前一篇文章中,咱们学会了 geo_point
的应用,此处应用地理位置查问并应用 java
语言实现一下。
性能:
1、实现查问、过滤。
2、实现聚合。
3、实现排序。
4、实现后置过滤。
二、对应的 query 语句
GET geo_index/_search
{
"from": 0,
"size": 10,
"timeout": "20s",
"query": {
"bool": {
"must": [
{
"match_all": {"boost": 1.0}
}
],
"filter": [
{
"geo_distance": {
"location": [
121.462311,
31.256224
],
"distance": 3000.0,
"distance_type": "arc",
"validation_method": "STRICT",
"ignore_unmapped": false,
"boost": 1.0,
"_name": "optional_name"
}
}
],
"adjust_pure_negative": true,
"boost": 1.0
}
},
"post_filter": {
"geo_distance": {
"location": [
121.462311,
31.256224
],
"distance": 1000.0,
"distance_type": "arc",
"validation_method": "STRICT",
"ignore_unmapped": false,
"boost": 1.0
}
},
"sort": [
{
"_geo_distance": {
"location": [
{
"lat": 31.256224,
"lon": 121.462311
}
],
"unit": "m",
"distance_type": "arc",
"order": "desc",
"validation_method": "STRICT",
"ignore_unmapped": false
}
}
],
"aggregations": {
"distanceAgg": {
"geo_distance": {
"field": "location",
"origin": {
"lat": 31.256224,
"lon": 121.462311
},
"ranges": [
{
"key": "first",
"from": 0.0,
"to": 500.0
},
{
"key": "second",
"from": 500.0,
"to": 1000.0
},
{
"key": "third",
"from": 1000.0
}
],
"keyed": true,
"unit": "m",
"distance_type": "ARC"
}
}
}
}
三、对应 java 代码
1、引入 jar 包
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.7.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.12.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
</dependencies>
2、创立 RestHighLevelClient
public class AbstractEsApi {
protected final RestHighLevelClient client;
public AbstractEsApi() {
client = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http"),
new HttpHost("localhost", 9202, "http")
)
);
}
}
3、实现查问
import com.huan.study.esapi.AbstractEsApi;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.ShardSearchFailure;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.range.ParsedGeoDistance;
import org.elasticsearch.search.aggregations.bucket.range.Range;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.GeoDistanceSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.Arrays;
/**
* distance query 类型的 地理位置查问
*
* @author huan.fu 2021/4/22 - 下午 4:00
*/
public class DistanceQueryApi extends AbstractEsApi {@DisplayName("间隔查问")
@Test
public void distanceQueryTest() throws IOException {
// 查问申请
SearchRequest searchRequest = new SearchRequest("geo_index");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 从索引那个开始返回数据
searchSourceBuilder.from(0);
// 查问多少条记录
searchSourceBuilder.size(10);
// 查问超时工夫
searchSourceBuilder.timeout(TimeValue.timeValueSeconds(20));
// 结构查问和过滤数据
searchSourceBuilder.query(
// 结构布尔查问
QueryBuilders.boolQuery()
// 查问语句
.must(QueryBuilders.matchAllQuery()
)
// 过滤语句
.filter(
// name 是过滤的字段
QueryBuilders.geoDistanceQuery("location")
// 在 3km 之内
.distance("3", DistanceUnit.KILOMETERS)
// 以那个点为核心
.point(31.256224D, 121.462311D)
.geoDistance(GeoDistance.ARC)
// 一个查问的名字,可选
.queryName("optional_name")
)
);
// 后置过滤
searchSourceBuilder.postFilter(
// name 是过滤的字段
QueryBuilders.geoDistanceQuery("location")
// 在 3km 之内
.distance("1", DistanceUnit.KILOMETERS)
// 以那个点为核心
.point(31.256224D, 121.462311D)
);
// 排序
searchSourceBuilder.sort(
// 不同的类型应用不同的 SortBuilder
new GeoDistanceSortBuilder("location", 31.256224D, 121.462311D)
.order(SortOrder.DESC)
.unit(DistanceUnit.METERS)
.geoDistance(GeoDistance.ARC)
);
// 聚合操作
searchSourceBuilder.aggregation(
// name 聚合的名字 point 以那个点为核心开始聚合
AggregationBuilders.geoDistance("distanceAgg", new GeoPoint(31.256224D, 121.462311D))
// 字段
.field("location")
.unit(DistanceUnit.METERS)
.distanceType(GeoDistance.ARC)
.keyed(true)
// 范畴
.addRange("first", 0.0D, 500D)
.addRange("second", 500D, 1000D)
.addRange("third", 1000D, Double.NEGATIVE_INFINITY)
);
searchRequest.source(searchSourceBuilder);
System.out.println("查问语句:" + searchSourceBuilder.toString());
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("查问后果:" + searchResponse);
RestStatus status = searchResponse.status();
System.out.println(status.getStatus());
System.out.println(searchResponse.isTerminatedEarly());
System.out.println(searchResponse.isTimedOut());
for (ShardSearchFailure shardFailure : searchResponse.getShardFailures()) {System.out.println(shardFailure);
}
// 匹配到的后果
for (SearchHit hit : searchResponse.getHits().getHits()) {
// 数据
System.out.println(hit.getSourceAsMap());
// 排序间隔
Object[] sortValues = hit.getSortValues();
System.out.println(Arrays.toString(sortValues));
System.out.println("=====");
}
// 获取聚合的后果
Aggregations aggregations = searchResponse.getAggregations();
aggregations.getAsMap().forEach((key, value) -> {System.out.println("key:" + key);
for (Range.Bucket bucket : ((ParsedGeoDistance) value).getBuckets()) {System.out.println("from:" + bucket.getFromAsString() + "to:" + bucket.getToAsString() + "value:" + bucket.getDocCount());
}
System.out.println("------------");
});
}
}
1、输入查问语句
应用输入 SearchSourceBuilder
的后果即可。
2、输入响应后果
间接输入 SearchResponse
的后果即可。
至此就实现了上方的查问。
四、注意事项
- java high level rest client 的版本最好和咱们的
es
的版本统一,如果不统一,那么最好要和主版本统一。 - jdk 的版本起码要是
1.8
的版本。 - 不举荐应用
TransportClient
,这个曾经过期了,在es8
中将会移除。 - 输入咱们本人的查问语句,间接输入
SearchSourceBuilder
即可。 - 输入响应语句,间接输入
SearchResponse
即可。
五、残缺代码门路
https://gitee.com/huan1993/spring-cloud-parent/blob/master/es/es-api/src/test/java/com/huan/study/esapi/dslapi/geoapi/DistanceQueryApi.java
六、参考文档
1、https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.12/java-rest-high-query-builders.html
2、https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.12/java-rest-high-search.html
正文完