一、需要

在前一篇文章中,咱们学会了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的后果即可。

至此就实现了上方的查问。

四、注意事项

  1. java high level rest client 的版本最好和咱们的es的版本统一,如果不统一,那么最好要和主版本统一。
  2. jdk的版本起码要是1.8的版本。
  3. 不举荐应用 TransportClient,这个曾经过期了,在es8中将会移除。
  4. 输入咱们本人的查问语句,间接输入 SearchSourceBuilder即可。
  5. 输入响应语句,间接输入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