mongodb支持空间索引,其内部是B-Tree实现(是的,并不是R-Tree),本文展示常用的操作及spring访问的例子。
从github上下载数据并导入,你可能需要使用-u
,-p
参数指定用户名和密码。
wget https://raw.githubusercontent.com/mongodb/docs-assets/geospatial/neighborhoods.json && \
mongoimport neighborhoods.json -c neighborhoods
wget https://raw.githubusercontent.com/mongodb/docs-assets/geospatial/restaurants.json && \
mongoimport restaurants.json -c restaurants
创建空间索引
db.restaurants.createIndex({ location: "2dsphere" })
db.neighborhoods.createIndex({ geometry: "2dsphere" })
样例数据中包含一个点集和(restaurants
)和一个多边形集合(neighborhoods
), 内容如下
> db.restaurants.findOne()
{
"_id" : ObjectId("55cba2476c522cafdb053ae0"),
"location" : {
"coordinates" : [
-73.8601152,
40.7311739
],
"type" : "Point"
},
"name" : "Tov Kosher Kitchen"
}
> db.neighborhoods.findOne()
{
"_id" : ObjectId("55cb9c666c522cafdb053a1a"),
"geometry" : {
"coordinates" : [
[
[
-73.94193078816193,
40.70072523469547
],
...
[
-73.94193078816193,
40.70072523469547
]
]
],
"type" : "Polygon"
},
"name" : "Bedford"
}
查询500米以内的所有餐厅(点),并从近到远排序返回
db.restaurants.find({
location: {
$near: {
$geometry: {
type: "Point",
coordinates: [-73.93414657, 40.82302903]
},
$maxDistance: 500
}
}
})
Point point = new Point(-73.93414657, 40.82302903);
Distance distance = new Distance(0.5, Metrics.KILOMETERS);
List<Restaurant> restaurants = restaurantRepository.findByLocationNear(point, distance);
查询经纬度偏差0.001度以内所有的餐厅(点),返回是无序的
db.restaurants.find({
location: {
$geoWithin: { $center: [ [-74, 40.74], 0.001 ] }
}
})
Circle circle = new Circle(
new Point(-74, 40.74),
new Distance(0.001)
);
List<Restaurant> restaurants = restaurantRepository.findByLocationWithin(circle);
查询当前点所在小区(多边形),再查找在小区内的所有餐厅(点)
var neighborhood = db.neighborhoods.findOne({
geometry: {
$geoIntersects: {
$geometry: {
type: "Point",
coordinates: [-73.93414657, 40.82302903]
}
}
}
})
db.restaurants.find({location: {$geoWithin: {$geometry: neighborhood.geometry}}}).count()
GeoJsonPoint point = new GeoJsonPoint( -73.93414657, 40.82302903);
Neighborhood neighborhood = mongoTemplate.findOne(
new Query(Criteria.where("geometry").intersects(point)),
Neighborhood.class);
System.out.println("find:" +
restaurantRepository.findByLocationWithin(neighborhood.getGeometry()).size());