一、需求

在前一篇文章中,我们学会了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、实现查询

1、方式一-使用api

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("------------");
});
}
}

2、方式二-之内传入json查询串

Request request = new Request("GET", "geo_index/_search");
// 需要查询的 json 字符串
String queryJsonEntity = "{\"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\"}}}}";
request.setJsonEntity(queryJsonEntity);
Response response = client.getLowLevelClient().performRequest(request);
String result = EntityUtils.toString(request.getEntity(), StandardCharsets.UTF_8);
System.out.println("响应结果: " + result);

3、输出查询语句

使用输出 SearchSourceBuilder 的结果即可。

4、输出响应结果

直接输出 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

Java High Level REST Client 使用地理位置查询的更多相关文章

  1. 使用Java Low Level REST Client操作elasticsearch

    Java REST客户端有两种风格: Java低级别REST客户端(Java Low Level REST Client,以后都简称低级客户端算了,难得码字):Elasticsearch的官方low- ...

  2. Java High Level REST Client 中文API(仅供参考)

    1.初始化 兼容性 Java High Level REST Client需要Java 1.8,并依赖于Elasticsearch核心项目,客户端版本与客户端开发的Elasticsearch版本相同, ...

  3. Elasticsearch java api操作(二)(Java High Level Rest Client)

    一.说明: 一.Elasticsearch提供了两个JAVA REST Client版本: 1.java low level rest client: 低级别的rest客户端,通过http与集群交互, ...

  4. Elasticsearch java api操作(一)(Java Low Level Rest Client)

    一.说明: 一.Elasticsearch提供了两个JAVA REST Client版本: 1.java low level rest client: 低级别的rest客户端,通过http与集群交互, ...

  5. 使用Java High Level REST Client操作elasticsearch

    Java高级别REST客户端(The Java High Level REST Client)以后简称高级客户端,内部仍然是基于低级客户端.它提供了更多的API,接受请求对象作为参数并返回响应对象,由 ...

  6. Java High Level REST Client 使用示例

    概述 ES 在 7.0 版本开始将废弃 TransportClient,8.0 版本开始将完全移除 TransportClient,取而代之的是 High Level REST Client,官方文档 ...

  7. 【ES】Java High Level REST Client 使用示例(增加修改)

    ES提供了多种编程语言的链接方式,有Java API,PHP API,.NET API 官网可以详细了解 https://www.elastic.co/guide/en/elasticsearch/c ...

  8. SpringBoot:elasticSearch 7.2.0 Java High Level REST Client 搜索 API

    Springboot整合最新版elasticSearch参考之前的文章:SpingBoot:整合ElasticSearch 7.2.0 Search API SearchRequest用于与搜索文档, ...

  9. SpringBoot:Java High Level REST Client 搜索 API

    Springboot整合最新版elasticSearch参考之前的文章:SpingBoot:整合ElasticSearch 7.2.0 Search API SearchRequest用于与搜索文档, ...

随机推荐

  1. 回收Windows 10恢复分区之后的磁盘空间

    我电脑上安装了Windows 10和Linux双系统,现在将Linux删除之后,准备将其磁盘空间并入到Windows 10的C盘中,但是发现C盘跟Linux空间之间还隔了一个Windows的恢复分区, ...

  2. (4)java Spring Cloud+Spring boot+mybatis企业快速开发架构之SpringCloud-Spring Cloud开发环境的准备和Lombok安装步骤

    ​ 开发环境的准备主要涉及三个方面:JDK.Maven.Spring Tools 4 for Eclipse. 1.JDK JDK 的版本用 1.8 即可,环境变量大家自行去配置.配置好环境变量,在命 ...

  3. selenium-ide-2.3.0 组件在foxfire45.0无法安装的问题

    楼主在安装selenium-ide组件时,尝试了下面两种方式都无法安装: 1.在forfire浏览器进行拖拽安装,页面无任何跳转.拖拽后回车安装,也没任何效果 2.附件组件-从文件安装添加组件,添加了 ...

  4. Django学习day01随堂笔记

    每日测验 """ 每日测验 1.你所知道的前端框架和实用插件有哪些,他们各有什么特点 2.使用bootstrap需要注意什么,常用的bootstrap样式有哪些 &quo ...

  5. Docker系列(24)- 实战:DockerFile制作tomcat镜像

    实战:DockerFile制作tomcat镜像 step-1 准备镜像文件 tomcat压缩包,jdk压缩包! step-2 编写dockerfile文件,官方命名Dockerfile,build会自 ...

  6. shell脚本中 /dev/null 的用途

    /dev/null 是一个特殊的设备文件,它丢弃一切写入其中的数据 可以将它 视为一个黑洞, 它等效于只写文件, 写入其中的所有内容都会消失, 尝试从中读取或输出不会有任何结果,同样,/dev/nul ...

  7. P1074 [NOIP2009 提高组] 靶形数独

    #include<bits/stdc++.h> using namespace std; const int N=10; int a[N][N],ans[N][N],vis[3][N][N ...

  8. 进入vim /etc/profile如何退出

    按o或i输入 按Esc,输入:wq,退出

  9. 使用php函数 json_encode ,数据存入mysql

    $data = json_encode($array); // 过滤 $data = addslashes($data); // 插入数据库 $db->insert($table_name,ar ...

  10. 鸿蒙内核源码分析(静态站点篇) | 五一哪也没去就干了这事 | 百篇博客分析OpenHarmony源码 | v52.02

    百篇博客系列篇.本篇为: v52.xx 鸿蒙内核源码分析(静态站点篇) | 五一哪也没去就干了这事 | 51.c.h.o 前因后果相关篇为: v08.xx 鸿蒙内核源码分析(总目录) | 百万汉字注解 ...