按地理空间搜索
Overview
在本指南中,您可以了解如何使用 MongoDB Java 驱动程序搜索地理空间数据,以及 MongoDB 支持的不同地理空间数据格式。
地理空间数据是表示地球表面地理位置的数据。 地理空间数据的示例包括:
电影院位置
国家/地区边界
自行车骑行路线
纽约市的狗狗运动区
地球坐标
要在 MongoDB 中存储和查询地理空间数据,请使用GeoJSON 。 GeoJSON 是由互联网工程任务组 (IETF) 创建的一种数据格式。
以下是 GeoJSON 中 MongoDB 总部的位置:
"MongoDB Headquarters" : { "type": "point", "coordinates": [-73.986805, 40.7620853] }
有关 GeoJSON 的确切信息,请参阅 IETF 官方规范。
GeoJSON 位置
位置表示地球上的单个位置,在代码中作为包含两个或三个数值的数组存在:
第一个位置的经度(必需)
第二个位置的纬度(必需)
第三个位置的海拔高度(选填)
重要
经度然后纬度
GeoJSON 将坐标排序为经度在前,纬度在后。 这可能令人惊讶,因为地理坐标系惯例通常首先列出纬度,然后列出经度。 请务必检查您正在使用的其他工具所使用的格式。 OpenStreetMap 和 Google Maps 等流行工具以纬度在前、经度在后的方式列出坐标。
GeoJSON 类型
GeoJSON 对象的类型决定了其几何形状。 几何形状由多个位置组成。
下面是一些常见的 GeoJSON 类型以及如何使用位置指定这些类型:
Point
:单个位置。 这可以代表 雕塑的位置。LineString
:由两个或多个位置组成的数组,从而形成一系列线段。 这可能代表 中国长城的路线。Polygon
:位置数组,其中第一个和最后一个位置相同,因此包含一些空格。 这可能代表 梵蒂冈城内的土地。
要进一步了解可在 MongoDB 中使用的形状,请参阅GeoJSON 手册条目。
Index
要查询以 GeoJSON 格式存储的数据,请将包含 GeoJSON 数据的字段添加到2dsphere
索引中。 以下代码片段使用Indexes
构建器在location.geo
字段上创建2dsphere
索引:
// <MongoCollection setup code here> collection.createIndex(Indexes.geo2dsphere("location.geo"));
有关Indexes
构建器的更多信息,请参阅我们有关索引构建指南的指南。
2D 平面上的坐标
您可以使用二维欧几里得平面上的x
和y
坐标来存储地理空间数据。 我们将二维平面上的坐标称为“legacy coordinate pairs”。
legacy coordinate pairs 具有以下结构:
"<field name>" : [ x, y ]
您的字段应包含一个由两个值组成的数组,其中第一个值代表 x
轴值,第二个值代表 y
轴值。
Index
要查询存储为传统坐标对的数据,必须将包含传统坐标对的字段添加到2d
索引中。 以下代码片段使用Indexes
构建器在coordinates
字段上创建2d
索引:
// <MongoCollection setup code here> collection.createIndex(Indexes.geo2d("coordinates"));
有关Indexes
构建器的更多信息,请参阅我们的索引构建器指南。
legacy coordinate pairsMongoDB Server有关legacy coordinate pairs 的 手册页面。
地理空间查询
地理空间查询由查询操作符和作为查询参数的 GeoJSON 形状组成。
查询运算符
要查询地理空间数据,请使用以下查询运算符之一:
$near
$geoWithin
$nearSphere
$geoIntersects
需要 2dsphere 索引
您可以使用Filters
构建器类的near()
、 geoWithin()
、 nearSphere()
和geoIntersects()
实用程序方法在 MongoDB Java 驱动程序中指定这些查询操作符。
有关地理空间查询操作符的更多信息,请参阅地理空间查询的对应手册条目。
有关Filters
的更多信息,请参阅我们的筛选器构建器指南。
查询参数
要指定在地理空间查询中使用的形状,请使用 MongoDB Java 驱动程序的Position
、 Point
、 LineString
和Polygon
类。
有关 MongoDB Java 驱动程序中可用的 GeoJSON 形状的完整列表,请参阅 GeoJSON 包 API 文档。
示例
以下示例使用 MongoDB Atlas 样本数据集。您可以学习如何设置自己的免费套餐 Atlas 集群,并在我们的快速入门指南中了解如何加载样本数据集。
示例使用了样本数据集 sample_mflix
数据库中的 theaters
集合。theaters
集合包含 location.geo
字段上的 2dsphere
索引。
这些示例需要进行以下导入:
import java.util.Arrays; import org.bson.conversions.Bson; import com.mongodb.client.model.geojson.Point; import com.mongodb.client.model.geojson.Polygon; import com.mongodb.client.model.geojson.Position; import static com.mongodb.client.model.Filters.near; import static com.mongodb.client.model.Filters.geoWithin; import static com.mongodb.client.model.Projections.fields; import static com.mongodb.client.model.Projections.include; import static com.mongodb.client.model.Projections.excludeId;
您可以 在此处找到 Github上示例的源代码。
按距离查询
要按从最近到最远的顺序搜索并返回文档,请使用Filters
构建器类的near()
静态实用程序方法。 near()
方法使用$near
查询运算符构造查询。
以下示例查询距离10,000
5,000
中央公园大草坪 到 米之间的剧院。
// Add your MongoClient setup code here MongoDatabase database = mongoClient.getDatabase("sample_mflix"); MongoCollection<Document> collection = database.getCollection("theaters"); Point centralPark = new Point(new Position(-73.9667, 40.78)); // Creates a query that matches all locations between 5,000 and 10,000 meters from the specified Point Bson query = near("location.geo", centralPark, 10000.0, 5000.0); // Creates a projection to include only the "location.address.city" field in the results Bson projection = fields(include("location.address.city"), excludeId()); // Prints the projected field of the results from the geospatial query as JSON collection.find(query) .projection(projection) .forEach(doc -> System.out.println(doc.toJson()));
代码片段的输出应如下所示:
{"location": {"address": {"city": "Bronx"}}} {"location": {"address": {"city": "New York"}}} {"location": {"address": {"city": "New York"}}} {"location": {"address": {"city": "Long Island City"}}} {"location": {"address": {"city": "New York"}}} {"location": {"address": {"city": "Secaucus"}}} {"location": {"address": {"city": "Jersey City"}}} {"location": {"address": {"city": "Elmhurst"}}} {"location": {"address": {"city": "Flushing"}}} {"location": {"address": {"city": "Flushing"}}} {"location": {"address": {"city": "Flushing"}}} {"location": {"address": {"city": "Elmhurst"}}}
有关$near
操作符的更多信息,请参阅$near 的参考文档。
有关Filters
的更多信息,请参阅我们的筛选器构建器指南。
在范围内查询
要搜索指定形状内的地理空间数据,请使用Filters
构建器类的geoWithin()
静态实用程序方法。 geoWithin()
方法使用$geoWithin
查询运算符构造查询。
以下示例搜索长岛某个地区的电影院。
// Add your MongoCollection setup code here // Creates a set of points that defines the bounds of a geospatial shape Polygon longIslandTriangle = new Polygon(Arrays.asList(new Position(-72, 40), new Position(-74, 41), new Position(-72, 39), new Position(-72, 40))); // Creates a projection to include only the "location.address.city" field in the results Bson projection = fields(include("location.address.city"), excludeId()); // Creates a query that matches documents containing "location.geo" values within the specified bounds Bson geoWithinComparison = geoWithin("location.geo", longIslandTriangle); // Prints the projected field of the results from the geolocation query as JSON collection.find(geoWithinComparison) .projection(projection) .forEach(doc -> System.out.println(doc.toJson()));
代码片段的输出应如下所示:
{"location": {"address": {"city": "Baldwin"}}} {"location": {"address": {"city": "Levittown"}}} {"location": {"address": {"city": "Westbury"}}} {"location": {"address": {"city": "Mount Vernon"}}} {"location": {"address": {"city": "Massapequa"}}}
下图显示了由longIslandTriangle
变量定义的多边形以及表示查询返回的电影院位置的点。
有关$geoWithin
操作符的更多信息,请参阅$geoWithin 的参考文档
有关可在查询中使用的操作符的更多信息,请参阅有关地理空间查询操作符的 MongoDB Server 手册页面