ES中经纬度查询geo_point

0. ES版本

6.x版本

1. 创建索引

PUT /location
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0
  },
  "mappings": {
    "location": {
      "properties": {
        "id": {
          "type": "keyword"
        },
        "name": {
          "type": "text",
          "analyzer": "ik_max_word",
          "search_analyzer": "ik_max_word"
        },
        "coordinate": {
          "type": "geo_point"
        }
      }
    }
  }
}

2. 批量插入数据

注意:这里的coordinate用的是字符串插入,所以要用纬经度。试了下用数组的形式(“coordinate”:[116.64002551005981,40.17836693398477])会报错,应该是6.x的版本不支持吧

PUT /location/location/_bulk
{"index":{"_id":"1"}}
{"name":"资料名称1","coordinate":"40.17836693398477,116.64002551005981"}
{"index":{"_id":"2"}}
{"name":"资料名称2","coordinate":"40.19103839805197,116.5624013764374"}
{"index":{"_id":"3"}}
{"name":"资料名称3","coordinate":"40.13933715136454,116.63441990026217"}
{"index":{"_id":"4"}}
{"name":"资料名称4","coordinate":"40.14901664712196,116.53067995860928"}
{"index":{"_id":"5"}}
{"name":"资料名称5","coordinate":"40.125057718315716,116.62963567059545"}
{"index":{"_id":"6"}}
{"name":"资料名称6","coordinate":"40.19216257806647,116.64025980109571"}
{"index":{"_id":"7"}}
{"name":"资料名称7","coordinate":"40.16371689899584,116.63095084701624"}
{"index":{"_id":"8"}}
{"name":"资料名称8","coordinate":"40.146045218040605,116.5696251832195"}
{"index":{"_id":"9"}}
{"name":"资料名称9","coordinate":"40.144735806234166,116.60712460957835"}

3. geo_bounding_box查询

3.1 解释

geo_bounding_box是查询一个矩形内的所有数据,提供左上角和右上角的经纬度坐标
在这里插入图片描述

3.2 经纬度属性查询

GET /location/location/_search
{
  "query": {
    "geo_bounding_box": {
      "coordinate": {
        "top_left": {
          "lat": 40.187328,
          "lon": 116.498353
        },
        "bottom_right": {
          "lat": 40.084509,
          "lon": 116.610461
        }
      }
    }
  }
}

3.3 经纬度数组查询

GET /location/location/_search
{
  "query": {
    "geo_bounding_box": {
      "coordinate": {
        "top_left": [116.498353, 40.187328],
        "bottom_right": [116.610461, 40.084509]
      }
    }
  }
}

3.4 经纬度字符串查询

GET /location/location/_search
{
  "query": {
    "geo_bounding_box": {
      "coordinate": {
        "top_left": "40.187328, 116.498353",
        "bottom_right": "40.084509, 116.610461"
      }
    }
  }
}

3.5 经纬度边界框WKT查询

GET /location/location/_search
{
  "query": {
    "geo_bounding_box": {
      "coordinate": {
        "wkt": "BBOX(116.498353,116.610461,40.187328,40.084509)"
      }
    }
  }
}

3.6 经纬度顶点属性查询

GET /location/location/_search
{
  "query": {
    "geo_bounding_box": {
      "coordinate": {
        "top": 40.187328,
        "left": 116.498353,
        "bottom": 40.084509,
        "right": 116.610461
      }
    }
  }
}

4. geo_polygon查询

4.1 解释

geo_polygon查询一个多边形区域内的所有数据,需要按顺序形成一个闭合的区域,不管从哪个坐标开始,只要能形成一个闭合区域就行
在这里插入图片描述

4.2 查询

GET /location/location/_search
{
  "query": {
    "geo_polygon": {
      "coordinate": {
        "points": [
          "40.178012,116.577188",
          "40.169329,116.586315",
          "40.178288,116.591813"
        ]
      }
    }
  }
}
GET /location/location/_search
{
  "query": {
    "geo_polygon": {
      "coordinate": {
        "points": [
          "40.178012,116.577188",
          "40.169329,116.586315",
          "40.178288,116.591813",
          "40.171975,116.587105"
        ]
      }
    }
  }
}

5. Springboot中使用geo_bounding_box查询

5.1 实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = "location", type = "location")
public class AddressEsEntity {
    @Id
    private String id;

    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String name;

    @Field(type = FieldType.Keyword)
    private String coordinate;
}

5.2 geoBoundingBoxQuery

这里的setCorners里面直接传topLeft和bottomRight会报错,具体原因还没研究

String topLeft = "40.187328,116.498353";
String bottomRight = "40.084509,116.610461";
try {
    SearchRequest searchRequest = new SearchRequest("location");
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    searchSourceBuilder.query(QueryBuilders.geoBoundingBoxQuery("coordinate")
            .setCorners(new GeoPoint("40.187328,116.498353"), new GeoPoint("40.084509,116.610461")));
    searchRequest.types("location").source(searchSourceBuilder);
    SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    SearchHit[] hits = searchResponse.getHits().getHits();
    System.out.println(searchResponse);
} catch (IOException e) {
    e.printStackTrace();
}

5.3 geoPolygonQuery

List<GeoPoint> points = new ArrayList<>();
points.add(new GeoPoint("40.178012,116.577188"));
points.add(new GeoPoint("40.169329,116.586315"));
points.add(new GeoPoint("40.178288,116.591813"));
try {
    SearchRequest searchRequest = new SearchRequest("address");
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    searchSourceBuilder.query(QueryBuilders.geoPolygonQuery("coordinate", points));
    searchRequest.types("address").source(searchSourceBuilder);
    SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    SearchHit[] hits = searchResponse.getHits().getHits();
    System.out.println(searchResponse);
} catch (IOException e) {
    e.printStackTrace();
}
要在Spring Boot中使用ElasticsearchEs)根据`geo_point`类型字段查询附近20km的用户数据,并根据距离由近至远排序,同时将距离返回到相应数据中,可以按照以下步骤进行: 1. **引入依赖**:在`pom.xml`中添加Elasticsearch相关依赖。 2. **配置Elasticsearch**:在`application.properties`或`application.yml`中配置Elasticsearch连接信息。 3. **定义实体类**:定义包含`geo_point`字段的用户实体类。 4. **创建Repository**:创建Elasticsearch Repository接口。 5. **编写服务层**:编写服务层代码,实现查询逻辑。 以下是一个完整的示例: ### 1. 引入依赖 在`pom.xml`中添加以下依赖: ```xml <dependencies> <!-- Elasticsearch --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <!-- 其他依赖 --> </dependencies> ``` ### 2. 配置Elasticsearch 在`application.properties`中添加以下配置: ```properties spring.elasticsearch.uris=http://localhost:9200 ``` ### 3. 定义实体类 ```java import org.springframework.data.elasticsearch.annotations.GeoPointField; import org.springframework.data.elasticsearch.core.geo.GeoPoint; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; @Document(indexName = "users") public class User { @Id private String id; private String name; @GeoPointField private GeoPoint location; // Getters and Setters } ``` ### 4. 创建Repository ```java import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import org.springframework.stereotype.Repository; @Repository public interface UserRepository extends ElasticsearchRepository<User, String> { } ``` ### 5. 编写服务层 ```java import org.elasticsearch.common.geo.GeoDistance; import org.elasticsearch.common.unit.DistanceUnit; import org.elasticsearch.index.query.GeoDistanceQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.sort.GeoDistanceSortBuilder; import org.elasticsearch.search.sort.SortBuilders; import org.elasticsearch.search.sort.SortOrder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.core.SearchHit; import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.stereotype.Service; import java.util.List; import java.util.stream.Collectors; @Service public class UserService { @Autowired private ElasticsearchOperations elasticsearchOperations; public List<User> findNearbyUsers(double latitude, double longitude) { GeoDistanceQueryBuilder geoDistanceQuery = QueryBuilders.geoDistanceQuery("location") .point(latitude, longitude) .distance(20, DistanceUnit.KILOMETERS) .geoDistance(GeoDistance.ARC); GeoDistanceSortBuilder sortBuilder = SortBuilders.geoDistanceSort("location", latitude, longitude) .order(SortOrder.ASC) .unit(DistanceUnit.KILOMETERS); NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder() .withQuery(geoDistanceQuery) .withSort(sortBuilder); SearchHits<User> searchHits = elasticsearchOperations.search(queryBuilder.build(), User.class); return searchHits.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList()); } } ``` ### 6. 编写控制器 ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class UserController { @Autowired private UserService userService; @GetMapping("/findNearbyUsers") public List<User> findNearbyUsers(@RequestParam double latitude, @RequestParam double longitude) { return userService.findNearbyUsers(latitude, longitude); } } ``` 通过以上步骤,你就可以实现根据`geo_point`字段查询附近20km的用户数据,并根据距离由近至远排序,同时将距离返回到相应数据中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值