Elasticsearch-经纬度查询(8.x)

2024-06-14 1444阅读

目录

一、开发环境

二、pom文件

三、ES配置文件

四、ES相关字段

五、ES半径查询


ES的字段类型:geo_point,可以实现以一个点为中心的半径查询(geo_distance query)

ES地理位置查询:

  • 半径查询(geo_distance query)
  • 查询指定矩形内的数据(geo_bounding_box query)
  • 查询指定多边形内的数据(geo_polygon query)

    官方文档:Geo queries | Elasticsearch Guide [8.14] | Elastic

    本案例实现以某个点的经纬,查询半径查询,并计算出其他点和中心点的距离

    一、开发环境

    工具版本
    JDK21
    SpringBoot3.2.4
    ElasticSearch8.13.2

    二、pom文件

            
            
                co.elastic.clients
                elasticsearch-java
                8.13.2
            

    三、ES配置文件

    properties:

    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import java.util.List;
    /**
     * ES 配置属性
     *
     * @author meng
     * @date 2024-05-07
     */
    @Data
    @ConfigurationProperties(prefix = "es")
    public class ElasticsearchProperties {
        /**
         * es 请求方式
         */
        private String scheme;
        /**
         * es 集群host ip 地址
         */
        private List hosts;
        /**
         * es 账号
         */
        private String username;
        /**
         * es 密码
         */
        private String password;
        /**
         * es 连接超时时间
         */
        private Integer connectTimeOut;
        /**
         * es socket 连接超时时间
         */
        private Integer socketTimeOut;
        /**
         * es 请求超时时间
         */
        private Integer connectionRequestTimeOut;
        /**
         * es 最大连接数
         */
        private Integer maxConnectNum;
        /**
         * es 每个路由的最大连接数
         */
        private Integer maxConnectNumPerRoute;
    }
    

    config:

    import co.elastic.clients.elasticsearch.ElasticsearchClient;
    import co.elastic.clients.json.jackson.JacksonJsonpMapper;
    import co.elastic.clients.transport.ElasticsearchTransport;
    import co.elastic.clients.transport.rest_client.RestClientTransport;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.http.HttpHost;
    import org.apache.http.auth.AuthScope;
    import org.apache.http.auth.UsernamePasswordCredentials;
    import org.apache.http.client.CredentialsProvider;
    import org.apache.http.conn.ssl.NoopHostnameVerifier;
    import org.apache.http.impl.client.BasicCredentialsProvider;
    import org.apache.http.ssl.SSLContextBuilder;
    import org.apache.http.ssl.TrustStrategy;
    import org.elasticsearch.client.RestClient;
    import org.elasticsearch.client.RestClientBuilder;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import javax.net.ssl.SSLContext;
    import java.security.KeyManagementException;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.time.Duration;
    /**
     * ES 配置类,当 es.enable=true 时自动配置
     *
     * @author meng
     * @date 2024-05-07
     */
    @Slf4j
    @Configuration
    @EnableConfigurationProperties(value = ElasticsearchProperties.class)
    @ConditionalOnProperty(prefix = "es", name = "enable")
    public class ElasticsearchConfig {
        @Bean(name = "ElasticsearchClient")
        public ElasticsearchClient initClient(ElasticsearchProperties elasticsearchProperties) {
            HttpHost[] esHosts = elasticsearchProperties.getHosts().stream().filter(StringUtils::isNotBlank).map(it -> {
                String[] split = it.split(":");
                return new HttpHost(split[0], Integer.parseInt(split[1]), elasticsearchProperties.getScheme());
            }).toArray(HttpHost[]::new);
            final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            credentialsProvider.setCredentials(AuthScope.ANY,
                    new UsernamePasswordCredentials(elasticsearchProperties.getUsername(),
                            elasticsearchProperties.getPassword()));
            RestClientBuilder restClientBuilder = RestClient.builder(esHosts);
            // 连接延时配置
            restClientBuilder.setRequestConfigCallback(requestConfigBuilder -> {
                requestConfigBuilder.setConnectTimeout(elasticsearchProperties.getConnectTimeOut());
                requestConfigBuilder.setSocketTimeout(elasticsearchProperties.getSocketTimeOut());
                requestConfigBuilder.setConnectionRequestTimeout(elasticsearchProperties.getConnectionRequestTimeOut());
                return requestConfigBuilder;
            });
            // HttpClient 连接数配置
            restClientBuilder.setHttpClientConfigCallback(httpClientBuilder -> {
                httpClientBuilder.setMaxConnTotal(elasticsearchProperties.getMaxConnectNum());
                httpClientBuilder.setMaxConnPerRoute(elasticsearchProperties.getMaxConnectNumPerRoute());
                return httpClientBuilder;
            });
            // 设置keepalive时间
            restClientBuilder.setHttpClientConfigCallback(requestConfig ->
                    requestConfig.setKeepAliveStrategy((response, context) -> Duration.ofMinutes(3).toMillis())
            );
            // 忽略HTTPS方式链接,SSL证书、主机名验证器
            restClientBuilder.setHttpClientConfigCallback(httpAsyncClientBuilder -> {
                httpAsyncClientBuilder.disableAuthCaching();
                httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                try {
                    // 创建一个信任所有证书的 TrustStrategy 策略
                    TrustStrategy acceptTrustStrategy = (chain, authType) -> true;
                    // 使用 SSLContextBuilder 创建 SSLContext
                    SSLContext sslContext = SSLContextBuilder.create().loadTrustMaterial(null, acceptTrustStrategy).build();
                    httpAsyncClientBuilder.setSSLContext(sslContext);
                } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
                    e.printStackTrace();
                }
                // 忽略主机名验证
                httpAsyncClientBuilder.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE);
                return httpAsyncClientBuilder;
            });
            RestClient restClient = restClientBuilder.build();
            // 使用Jackson映射器创建传输层
            ElasticsearchTransport transport = new RestClientTransport(
                    restClient, new JacksonJsonpMapper()
            );
            ElasticsearchClient client = new ElasticsearchClient(transport);
            return client;
        }
    }
    

    四、ES相关字段

    Elasticsearch-经纬度查询(8.x)

    五、ES半径查询

    具体查询对象,可自行定义,本方法只提供思路,莫直接粘贴使用

    	@Resource
        private ElasticsearchClient esClient;
    	/**
    	 * 功能描述: 根据经纬度判断十米内是否有poi数据
    	 *
    	 * @Param: [request]
    	 * @Author: meng
    	 * @Date: 2024/6/6 19:57
    	 */
    	private PoiDTO getPoiNear(PoiRequest request) {
    		if (Objects.isNull(request.getLongitude()) && Objects.isNull(request.getLatitude())) {
    			return null;
    		}
    		// 中心点查询
    		GeoLocation geoLocation = new GeoLocation.Builder().latlon(
    				l -> l.lon(request.getLongitude().doubleValue()).lat(request.getLatitude().doubleValue())).build();
    		GeoDistanceQuery geoDistanceQuery = GeoDistanceQuery.of(
    				geoDis -> geoDis.field(PoiIndexConstant.LOCATION).location(geoLocation)
    						.distance(PoiIndexConstant.DISTANCE).distanceType(GeoDistanceType.Arc));
    		// 排序
    		List sorts = new ArrayList();
    		// 距离排序 米
    		GeoDistanceSort geoDistanceSort = GeoDistanceSort.of(
    				geoDis -> geoDis.field(PoiIndexConstant.LOCATION).location(geoLocation).order(SortOrder.Asc)
    						.unit(DistanceUnit.Meters));
    		SortOptions sortOptions = SortOptions.of(sort -> sort.geoDistance(geoDistanceSort));
    		sorts.add(sortOptions);
    		SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder();
    		searchRequestBuilder.index(PoiIndexConstant.INDEX_READ)
    				.query(query -> query.bool(builder -> builder.filter(f -> f.geoDistance(geoDistanceQuery)))).sort(sorts)
    				.size(CommonConstant.DEFAULT_NUM);
    		// ES查询
    		SearchRequest searchRequest = searchRequestBuilder.build();
    		log.info("getPoiNear query:{}", searchRequest.toString());
    		try {
                SearchResponse searchResponse = esClient.search(searchRequest, PoiIndex.class);
                // 未查到数据
    			if (Objects.nonNull(searchResponse.hits().total()) && searchResponse.hits().total().value() == 0) {
    				return null;
    			}
    			for (Hit hit : searchResponse.hits().hits()) {
    				if (ObjectUtil.isNotNull(hit.source())) {
    					PoiIndex poiIndex = BeanUtil.copyProperties(hit.source(), PoiIndex.class);
    					return BeanUtil.copyProperties(poiIndex, PoiDTO.class);
    				}
    			}
            } catch (Exception e) {
                log.error("es searchRequest Exception:", e);
                throw new ServiceException("searchRequest Exception");
            }
    		return null;
    	}
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]