一、需求

在前一篇文章中,我们学会了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. 第09课:GDB 实用调试技巧(下)

    本节课的核心内容: 多线程下禁止线程切换 条件断点 使用 GDB 调试多进程程序 多线程下禁止线程切换 假设现在有 5 个线程,除了主线程,工作线程都是下面这样的一个函数: void thread_p ...

  2. JS014. toFixed( )调试踩坑 - 浏览器思维 点常量 & 点运算符

    Number.prototype.toFixed( ) 在观察toFixed()丢失精度问题,和对toFixed()方法重写的调试过程时,发现toFixed()对Number的识别有它自己的规则,并找 ...

  3. 一文了解Promise使用与实现

    前言 Promise 作为一个前端必备技能,不管是从项目应用还是面试,都应该对其有所了解与使用. 常常遇到的面试五连问: 说说你对 Promise 理解? Promise 的出现解决了什么问题? Pr ...

  4. Java学习笔记--常用容器

    容器 1. 出现原因 解决程序运行时需要创建新对象,在程序运行前不知道运行的所需的对象数量甚至是类型的问题. Java中提供了一套集合类来解决这些问题包括:List.Set.Queue.Map 2. ...

  5. 用Python实现童年的21款小游戏,有你玩过的吗?(不要错过哦)

    Python为什么能这么火热,Python相对于其他语言来说比较简单,即使是零基础的普通人也能很快的掌握,在其他方面比如,处于灰色界的爬虫,要VIP的视频,小说,歌,没有爬虫解决不了的:数据挖掘及分析 ...

  6. html5 sessionStorage util

      /** * Created by 13352 on 2018/7/5. */ define(function() { var session = { _id: null, _cookieCache ...

  7. shell加密为二进制可执行文件

    1.下载shc工具 http://www.datsi.fi.upm.es/~frosal/sources/shc-3.8.9.tgz或者到http://www.datsi.fi.upm.es/~fro ...

  8. 华为云计算IE面试笔记-华为云计算解决方案业务迁移支持哪些迁移?有哪些特点?请描述基本的业务交付流程、业务迁移流程和原则。

    1. 迁移场景:华为云计算解决方案按照源端环境来说,支持P2V.V2V(P2V:物理设备(操作系统及其上的应用软件和数据)迁移到华为虚拟化平台.V2V:其他厂商的虚拟化平台迁移到华为虚拟化平台.)以及 ...

  9. Loj#3026-「ROIR 2018 Day1」管道监控【Trie,费用流】

    正题 题目链接:https://loj.ac/p/3026 题目大意 给出\(n\)个点的一棵外向树,然后\(m\)个字符串和费用表示你每次可以花费这个费用覆盖路径字符串和给出字符串相等的路径,求覆盖 ...

  10. 计算机网络-4-1-2-分类的IP地址

    有关IP最重要的文档就是互联网的正式标准RFC 791 IP地址及其表示方法 整个互联网就是一个单一,抽象的网络,IP地址就是给互联网上的每一台主机(或者路由器)的每一个接口分配一个在全世界范围内都是 ...