关于java:Java-High-Level-REST-Client-使用地理位置查询

4次阅读

共计 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的后果即可。

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

四、注意事项

  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

正文完
 0