地理空间查询是否适用于数组? ($geoWithin, $geoIntersects)
Do geospatial queries work on arrays? ( $geoWithin, $geoIntersects )
我有如下文件存储在MongoDB 3.0.5
{
"_id" : ObjectId("55f3a6ae0907233b5e9e7da0"),
"user" : {
"id" : "2d5b093ec8a3",
"regions" : [
{
"id" : NumberLong(1442365443852),
"name" : "penta",
"type" : "Polygon",
"center" : {
"lat" : -12.1254159880008100,
"lng" : -77.0316830277442930
},
"zoom" : 17.0000000000000000,
"coordinates" : [
[
-77.0322804898023610,
-12.1271067552781560
],
[
-77.0336792618036270,
-12.1255133434450870
],
[
-77.0326449349522590,
-12.1239143495252150
],
[
-77.0300991833209990,
-12.1238251884504540
],
[
-77.0299865305423740,
-12.1262000752832540
],
[
-77.0322804898023610,
-12.1271067552781560
]
]
},
{
"id" : NumberLong(1442366496200),
"name" : "triangle",
"type" : "Polygon",
"center" : {
"lat" : -12.1254749913046230,
"lng" : -77.0316598936915400
},
"zoom" : 17.0000000000000000,
"coordinates" : [
[
-77.0313568040728570,
-12.1266573492018090
],
[
-77.0325788855552670,
-12.1246968022373030
],
[
-77.0300653204321860,
-12.1246233756874440
],
[
-77.0313568040728570,
-12.1266573492018090
]
]
}
]
}
}
表示存储为多边形的 google 地图区域数组。我试图用几种替代方法查询它们,但 none 似乎有效,所以我想知道地理空间 MongoDB 查询是否适用于数组。
我的 Java 代码是:DBCursor docs = getCollection().find(search);
以下所有 6 个 'search' 查询 return 没有结果,但在几何上我希望匹配:
{ "user.regions" : { "$geoIntersects" : { "$geometry" : { "type" : "Polygon" , "coordinates" : [ [ [ -77.02877718955278 , -12.123750122669545] , [ -77.03457042574883 , -12.123750122669545] , [ -77.03457042574883 , -12.12736341792724] , [ -77.02877718955278 , -12.12736341792724] , [ -77.02877718955278 , -12.123750122669545]]]}}}}
{ "user.regions.0" : { "$geoIntersects" : { "$geometry" : { "type" : "Polygon" , "coordinates" : [ [ [ -77.02877718955278 , -12.123750122669545] , [ -77.03457042574883 , -12.123750122669545] , [ -77.03457042574883 , -12.12736341792724] , [ -77.02877718955278 , -12.12736341792724] , [ -77.02877718955278 , -12.123750122669545]]]}}}}
{ "user.regions.0.center" : { "$geoIntersects" : { "$geometry" : { "type" : "Polygon" , "coordinates" : [ [ [ -77.02877718955278 , -12.123750122669545] , [ -77.03457042574883 , -12.123750122669545] , [ -77.03457042574883 , -12.12736341792724] , [ -77.02877718955278 , -12.12736341792724] , [ -77.02877718955278 , -12.123750122669545]]]}}}}
{ "user.regions" : { "$geoWithin" : { "$geometry" : { "type" : "Polygon" , "coordinates" : [ [ [ -77.02877718955278 , -12.123750122669545] , [ -77.03457042574883 , -12.123750122669545] , [ -77.03457042574883 , -12.12736341792724] , [ -77.02877718955278 , -12.12736341792724] , [ -77.02877718955278 , -12.123750122669545]]]}}}}
{ "user.regions.0" : { "$geoWithin" : { "$geometry" : { "type" : "Polygon" , "coordinates" : [ [ [ -77.02877718955278 , -12.123750122669545] , [ -77.03457042574883 , -12.123750122669545] , [ -77.03457042574883 , -12.12736341792724] , [ -77.02877718955278 , -12.12736341792724] , [ -77.02877718955278 , -12.123750122669545]]]}}}}
{ "user.regions.0.center" : { "$geoWithin" : { "$geometry" : { "type" : "Polygon" , "coordinates" : [ [ [ -77.02877718955278 , -12.123750122669545] , [ -77.03457042574883 , -12.123750122669545] , [ -77.03457042574883 , -12.12736341792724] , [ -77.02877718955278 , -12.12736341792724] , [ -77.02877718955278 , -12.123750122669545]]]}}}}
我认为我尊重 MongoDB 中的 long/lat 顺序,我在我的多边形中重复了关闭点,我添加了 type="Polygon" 并且在中心的情况下点它在 lat/lng 参数下。但是没有结果。
我没有创建任何索引,我认为我匹配两个参数 geoWithin (http://docs.mongodb.org/manual/reference/operator/query/geoWithin/) and geoIntercepts (http://docs.mongodb.org/manual/reference/operator/query/geoIntersects/)
的语法
{
<location field>: {
$geoWithin: {
$geometry: {
type: <"Polygon" or "MultiPolygon"> ,
coordinates: [ <coordinates> ]
}
}
}
}
{
<location field>: {
$geoIntersects: {
$geometry: {
type: "<GeoJSON object type>" ,
coordinates: [ <coordinates> ]
}
}
}
}
关于 'location field' 我按照这里所说的数组说明进行操作 http://docs.mongodb.org/manual/tutorial/query-documents/
但是没有什么能让查询得到任何结果。我 googled for same case 我只能从 2013 年找到这个未解决的问题:How do I perform a find using $geoIntersects / 2dsphere in an array subfield?
所以,除非我犯了一个常见的错误,否则我想知道是否可以对数组参数进行地理空间查询?
有什么建议吗?
谢谢
这是要回答是和否的问题之一,因为是的,支持数组用于匹配结果,但考虑到对如何完成匹配的限制,它也可能不是您真正想要的。
此处您需要做的显着更改是,对象本身的定义方式无法让 MongoDB 识别您当前形成的对象。有两种索引和一般查找形式,它们要么带有遗留坐标对(只是一个 x,y 点),要么作为 GeoJSON 带有受支持的 GeoJSON 对象。您的问题是您的 "psuedo" GeoJSON 格式并不真正符合规范,并且您正试图直接访问 "coordinates",您需要像这样的顶级对象:
{
"regions": [
{
"name": "penta",
"geometry": {
"type": "Polygon",
"coordinates": [[
[
-77.0322804898023610,
-12.1271067552781560
],
[
-77.0336792618036270,
-12.1255133434450870
],
[
-77.0326449349522590,
-12.1239143495252150
],
[
-77.0300991833209990,
-12.1238251884504540
],
[
-77.0299865305423740,
-12.1262000752832540
],
[
-77.0322804898023610,
-12.1271067552781560
]
]]
}
},
{
"name": "triangle",
"geometry": {
"type": "Polygon",
"coordinates": [[
[
-77.0313568040728570,
-12.1266573492018090
],
[
-77.0325788855552670,
-12.1246968022373030
],
[
-77.0300653204321860,
-12.1246233756874440
],
[
-77.0313568040728570,
-12.1266573492018090
]
]]
}
}
]
}
因此,这将 GeoJSON 部分抽象为格式正确并与不属于规范的其他元数据分开。理想情况下,您也可以编制索引,尽管 $geoWithin
或 $geoIntersects
不需要,但它肯定有帮助:
db.regions.createIndex({ "regions.geometry": "2dsphere" })
正在数组元素中定义 GeoJSON 定义的完整路径。
然后查询正常工作:
db.regions.find({
"regions.geometry" : {
"$geoIntersects" : {
"$geometry" : {
"type" : "Polygon" ,
"coordinates" : [[
[ -77.02877718955278 , -12.123750122669545],
[ -77.03457042574883 , -12.123750122669545],
[ -77.03457042574883 , -12.12736341792724],
[ -77.02877718955278 , -12.12736341792724],
[ -77.02877718955278 , -12.123750122669545]
]]
}
}
}
})
与上面的文件相符。但是数组中当然有多个对象,那么问题来了,这些匹配的是哪个?没有支持的答案,因为 MongoDB 与 "document" 匹配并且不以任何方式指示哪个数组元素匹配。
聚合 $geoNear
中有一个选项允许对匹配的对象进行 return 编辑,在本例中为 "nearest"。有了这样的细节,就可以使用该信息来匹配哪个具有完整元数据的数组元素包含为 "nearest" 找到的元素并提取该数据。但同样它只是 "near" 并且也永远不会 return 来自数组的多个结果。
但一般来说,最好将单独的对象作为它们自己集合中的文档,其中与不同对象的匹配只是匹配文档的问题。因此,使用上面的数组在它自己的集合中,您只需发出匹配几何的查询:
db.shapes.find({
"geometry" : {
"$geoIntersects" : {
"$geometry" : {
"type" : "Polygon" ,
"coordinates" : [ [
[ -77.02877718955278 , -12.123750122669545],
[ -77.03457042574883 , -12.123750122669545],
[ -77.03457042574883 , -12.12736341792724],
[ -77.02877718955278 , -12.12736341792724],
[ -77.02877718955278 , -12.123750122669545]
]]
}
}
}
})
这给出了正确的对象,因为在这种情况下形状与两者相交:
{
"_id" : ObjectId("55f8d2fa66c2e7c750414b7a"),
"name" : "penta",
"geometry" : {
"type" : "Polygon",
"coordinates" : [[
[
-77.03228048980236,
-12.127106755278156
],
[
-77.03367926180363,
-12.125513343445087
],
[
-77.03264493495226,
-12.123914349525215
],
[
-77.030099183321,
-12.123825188450454
],
[
-77.02998653054237,
-12.126200075283254
],
[
-77.03228048980236,
-12.127106755278156
]
]]
}
}
{
"_id" : ObjectId("55f8d2fa66c2e7c750414b7b"),
"name" : "triangle",
"geometry" : {
"type" : "Polygon",
"coordinates" : [[
[
-77.03135680407286,
-12.126657349201809
],
[
-77.03257888555527,
-12.124696802237303
],
[
-77.03006532043219,
-12.124623375687444
],
[
-77.03135680407286,
-12.126657349201809
]
]]
}
}
因此您可以使用数组,但您只能真正匹配文档,而不是作为匹配一部分的单个数组成员,因此这 return 当然会将文档作为一个整体,您需要工作找出哪些成员符合客户端代码中的条件。
另一方面,您的几次查询尝试试图将对象坐标数组 "break up" 分解为单个元素。这根本不受支持,因为对象只能作为一个整体来处理,而不是 "Point" 个部分。
我有如下文件存储在MongoDB 3.0.5
{
"_id" : ObjectId("55f3a6ae0907233b5e9e7da0"),
"user" : {
"id" : "2d5b093ec8a3",
"regions" : [
{
"id" : NumberLong(1442365443852),
"name" : "penta",
"type" : "Polygon",
"center" : {
"lat" : -12.1254159880008100,
"lng" : -77.0316830277442930
},
"zoom" : 17.0000000000000000,
"coordinates" : [
[
-77.0322804898023610,
-12.1271067552781560
],
[
-77.0336792618036270,
-12.1255133434450870
],
[
-77.0326449349522590,
-12.1239143495252150
],
[
-77.0300991833209990,
-12.1238251884504540
],
[
-77.0299865305423740,
-12.1262000752832540
],
[
-77.0322804898023610,
-12.1271067552781560
]
]
},
{
"id" : NumberLong(1442366496200),
"name" : "triangle",
"type" : "Polygon",
"center" : {
"lat" : -12.1254749913046230,
"lng" : -77.0316598936915400
},
"zoom" : 17.0000000000000000,
"coordinates" : [
[
-77.0313568040728570,
-12.1266573492018090
],
[
-77.0325788855552670,
-12.1246968022373030
],
[
-77.0300653204321860,
-12.1246233756874440
],
[
-77.0313568040728570,
-12.1266573492018090
]
]
}
]
}
}
表示存储为多边形的 google 地图区域数组。我试图用几种替代方法查询它们,但 none 似乎有效,所以我想知道地理空间 MongoDB 查询是否适用于数组。
我的 Java 代码是:DBCursor docs = getCollection().find(search);
以下所有 6 个 'search' 查询 return 没有结果,但在几何上我希望匹配:
{ "user.regions" : { "$geoIntersects" : { "$geometry" : { "type" : "Polygon" , "coordinates" : [ [ [ -77.02877718955278 , -12.123750122669545] , [ -77.03457042574883 , -12.123750122669545] , [ -77.03457042574883 , -12.12736341792724] , [ -77.02877718955278 , -12.12736341792724] , [ -77.02877718955278 , -12.123750122669545]]]}}}}
{ "user.regions.0" : { "$geoIntersects" : { "$geometry" : { "type" : "Polygon" , "coordinates" : [ [ [ -77.02877718955278 , -12.123750122669545] , [ -77.03457042574883 , -12.123750122669545] , [ -77.03457042574883 , -12.12736341792724] , [ -77.02877718955278 , -12.12736341792724] , [ -77.02877718955278 , -12.123750122669545]]]}}}}
{ "user.regions.0.center" : { "$geoIntersects" : { "$geometry" : { "type" : "Polygon" , "coordinates" : [ [ [ -77.02877718955278 , -12.123750122669545] , [ -77.03457042574883 , -12.123750122669545] , [ -77.03457042574883 , -12.12736341792724] , [ -77.02877718955278 , -12.12736341792724] , [ -77.02877718955278 , -12.123750122669545]]]}}}}
{ "user.regions" : { "$geoWithin" : { "$geometry" : { "type" : "Polygon" , "coordinates" : [ [ [ -77.02877718955278 , -12.123750122669545] , [ -77.03457042574883 , -12.123750122669545] , [ -77.03457042574883 , -12.12736341792724] , [ -77.02877718955278 , -12.12736341792724] , [ -77.02877718955278 , -12.123750122669545]]]}}}}
{ "user.regions.0" : { "$geoWithin" : { "$geometry" : { "type" : "Polygon" , "coordinates" : [ [ [ -77.02877718955278 , -12.123750122669545] , [ -77.03457042574883 , -12.123750122669545] , [ -77.03457042574883 , -12.12736341792724] , [ -77.02877718955278 , -12.12736341792724] , [ -77.02877718955278 , -12.123750122669545]]]}}}}
{ "user.regions.0.center" : { "$geoWithin" : { "$geometry" : { "type" : "Polygon" , "coordinates" : [ [ [ -77.02877718955278 , -12.123750122669545] , [ -77.03457042574883 , -12.123750122669545] , [ -77.03457042574883 , -12.12736341792724] , [ -77.02877718955278 , -12.12736341792724] , [ -77.02877718955278 , -12.123750122669545]]]}}}}
我认为我尊重 MongoDB 中的 long/lat 顺序,我在我的多边形中重复了关闭点,我添加了 type="Polygon" 并且在中心的情况下点它在 lat/lng 参数下。但是没有结果。
我没有创建任何索引,我认为我匹配两个参数 geoWithin (http://docs.mongodb.org/manual/reference/operator/query/geoWithin/) and geoIntercepts (http://docs.mongodb.org/manual/reference/operator/query/geoIntersects/)
的语法{
<location field>: {
$geoWithin: {
$geometry: {
type: <"Polygon" or "MultiPolygon"> ,
coordinates: [ <coordinates> ]
}
}
}
}
{
<location field>: {
$geoIntersects: {
$geometry: {
type: "<GeoJSON object type>" ,
coordinates: [ <coordinates> ]
}
}
}
}
关于 'location field' 我按照这里所说的数组说明进行操作 http://docs.mongodb.org/manual/tutorial/query-documents/
但是没有什么能让查询得到任何结果。我 googled for same case 我只能从 2013 年找到这个未解决的问题:How do I perform a find using $geoIntersects / 2dsphere in an array subfield?
所以,除非我犯了一个常见的错误,否则我想知道是否可以对数组参数进行地理空间查询?
有什么建议吗?
谢谢
这是要回答是和否的问题之一,因为是的,支持数组用于匹配结果,但考虑到对如何完成匹配的限制,它也可能不是您真正想要的。
此处您需要做的显着更改是,对象本身的定义方式无法让 MongoDB 识别您当前形成的对象。有两种索引和一般查找形式,它们要么带有遗留坐标对(只是一个 x,y 点),要么作为 GeoJSON 带有受支持的 GeoJSON 对象。您的问题是您的 "psuedo" GeoJSON 格式并不真正符合规范,并且您正试图直接访问 "coordinates",您需要像这样的顶级对象:
{
"regions": [
{
"name": "penta",
"geometry": {
"type": "Polygon",
"coordinates": [[
[
-77.0322804898023610,
-12.1271067552781560
],
[
-77.0336792618036270,
-12.1255133434450870
],
[
-77.0326449349522590,
-12.1239143495252150
],
[
-77.0300991833209990,
-12.1238251884504540
],
[
-77.0299865305423740,
-12.1262000752832540
],
[
-77.0322804898023610,
-12.1271067552781560
]
]]
}
},
{
"name": "triangle",
"geometry": {
"type": "Polygon",
"coordinates": [[
[
-77.0313568040728570,
-12.1266573492018090
],
[
-77.0325788855552670,
-12.1246968022373030
],
[
-77.0300653204321860,
-12.1246233756874440
],
[
-77.0313568040728570,
-12.1266573492018090
]
]]
}
}
]
}
因此,这将 GeoJSON 部分抽象为格式正确并与不属于规范的其他元数据分开。理想情况下,您也可以编制索引,尽管 $geoWithin
或 $geoIntersects
不需要,但它肯定有帮助:
db.regions.createIndex({ "regions.geometry": "2dsphere" })
正在数组元素中定义 GeoJSON 定义的完整路径。
然后查询正常工作:
db.regions.find({
"regions.geometry" : {
"$geoIntersects" : {
"$geometry" : {
"type" : "Polygon" ,
"coordinates" : [[
[ -77.02877718955278 , -12.123750122669545],
[ -77.03457042574883 , -12.123750122669545],
[ -77.03457042574883 , -12.12736341792724],
[ -77.02877718955278 , -12.12736341792724],
[ -77.02877718955278 , -12.123750122669545]
]]
}
}
}
})
与上面的文件相符。但是数组中当然有多个对象,那么问题来了,这些匹配的是哪个?没有支持的答案,因为 MongoDB 与 "document" 匹配并且不以任何方式指示哪个数组元素匹配。
聚合 $geoNear
中有一个选项允许对匹配的对象进行 return 编辑,在本例中为 "nearest"。有了这样的细节,就可以使用该信息来匹配哪个具有完整元数据的数组元素包含为 "nearest" 找到的元素并提取该数据。但同样它只是 "near" 并且也永远不会 return 来自数组的多个结果。
但一般来说,最好将单独的对象作为它们自己集合中的文档,其中与不同对象的匹配只是匹配文档的问题。因此,使用上面的数组在它自己的集合中,您只需发出匹配几何的查询:
db.shapes.find({
"geometry" : {
"$geoIntersects" : {
"$geometry" : {
"type" : "Polygon" ,
"coordinates" : [ [
[ -77.02877718955278 , -12.123750122669545],
[ -77.03457042574883 , -12.123750122669545],
[ -77.03457042574883 , -12.12736341792724],
[ -77.02877718955278 , -12.12736341792724],
[ -77.02877718955278 , -12.123750122669545]
]]
}
}
}
})
这给出了正确的对象,因为在这种情况下形状与两者相交:
{
"_id" : ObjectId("55f8d2fa66c2e7c750414b7a"),
"name" : "penta",
"geometry" : {
"type" : "Polygon",
"coordinates" : [[
[
-77.03228048980236,
-12.127106755278156
],
[
-77.03367926180363,
-12.125513343445087
],
[
-77.03264493495226,
-12.123914349525215
],
[
-77.030099183321,
-12.123825188450454
],
[
-77.02998653054237,
-12.126200075283254
],
[
-77.03228048980236,
-12.127106755278156
]
]]
}
}
{
"_id" : ObjectId("55f8d2fa66c2e7c750414b7b"),
"name" : "triangle",
"geometry" : {
"type" : "Polygon",
"coordinates" : [[
[
-77.03135680407286,
-12.126657349201809
],
[
-77.03257888555527,
-12.124696802237303
],
[
-77.03006532043219,
-12.124623375687444
],
[
-77.03135680407286,
-12.126657349201809
]
]]
}
}
因此您可以使用数组,但您只能真正匹配文档,而不是作为匹配一部分的单个数组成员,因此这 return 当然会将文档作为一个整体,您需要工作找出哪些成员符合客户端代码中的条件。
另一方面,您的几次查询尝试试图将对象坐标数组 "break up" 分解为单个元素。这根本不受支持,因为对象只能作为一个整体来处理,而不是 "Point" 个部分。