问题描述
我将以下文档存储在MongoDB 3.0.5中
I have documents as the one below stored in 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地图区域.我正在尝试用几种替代方法来查询它们,但似乎都没有用,所以我想知道地理空间MongoDB查询是否可以在数组上使用.
which represents an array of google map regions stored as polygons. I am trying to query them with several alternatives but none seems to work so I am wondering if geospatial MongoDB queries works on arrays.
我的Java代码是:DBCursor docs = getCollection().find(search);
My Java code is: DBCursor docs = getCollection().find(search);
在几何上我期望匹配时,以下所有6个搜索"查询均不返回结果:
All the following 6 'search' queries return no results when geometrically I would expect a match:
-
{"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" : { "$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" : { "$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.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" : { "$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" : { "$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]]}}}}}}
{ "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中的长/纬度顺序,在多边形中重复闭合点,添加了type ="Polygon",并且在中心点的情况下,它位于lat/lng参数下.但是没有结果.
I think I am respecting the long/lat order in MongoDB, I repeat the closing point in my polygons, I have added type="Polygon" and in the case of the center point it is under lat/lng params. But no results.
我还没有创建任何索引,我认为我正在匹配两个参数geoWithin的语法( http://docs.mongodb.org/manual/reference/operator/query/geoWithin/)和geoIntercepts("> http://docs.mongodb.org/manual/reference/operator/query/geoIntersects/)
I have not created any indices and I think I am matching the syntax for both params 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> ]
}
}
}
}
关于位置字段",我按照此处的数组说明操作 http://docs.mongodb.org/manual/tutorial/query-documents/
Regarding 'location field' I followed instructions for arrays as said here http://docs.mongodb.org/manual/tutorial/query-documents/
但是没有什么可以使查询获得任何结果.我用谷歌搜索了同样的案件,但我只能从2013年找到这个未解决的问题:
But nothing makes the queries get any result. I googled for same case and I just could find this unsolved question from 2013: How do I perform a find using $geoIntersects / 2dsphere in an array subfield?
因此,除非我犯了一个常见错误,否则我想知道是否可以对数组参数进行地理空间查询?
So, unless I am doing a common mistake I am wondering if is possible to make geospatial queries to array params?
有什么建议吗?
谢谢
推荐答案
这是回答是和否的问题之一,因为支持匹配结果的数组,但考虑到匹配方式的限制,这可能也不是您真正想要的.
This is one of those both yes and no questions to answer, as yes an array is supported for matching results in but it is also probably not what you really want considering the restrictions on how the matching is done.
您需要在此处进行的显着更改是,对象本身的定义方式并非使MongoDB在您当前形成对象时就将其识别出来.有两种索引形式和常规查找形式,它们都具有旧式坐标对(只是一个x,y点)或作为 GeoJSON 和受支持的GeoJSON对象.您的问题是您使用的"psuedo" GeoJSON格式与规范不符,并且您尝试直接访问坐标",因此您需要像这样的顶级对象:
The notable change you need here is that the objects themselves are not defined in a way that MongoDB is going to recognise them as you currently have them formed. There are two index and general lookup forms being either with legacy coordinate pairs ( which is just an x,y point ) or as GeoJSON with supported GeoJSON objects. Your problem is you have a "psuedo" GeoJSON format that does not really conform to the spec, and that you are trying to access the "coordinates" directly, where you need a top level object like so:
{
"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
并不是必需的,它肯定会有所帮助:
So that abstracts the GeoJSON part to be both well formed and separated from the other meta data that is not part of the spec. Ideally you would index as well, though not required for $geoWithin
or $geoIntersects
it certainly helps:
db.regions.createIndex({ "regions.geometry": "2dsphere" })
在数组元素中定义GeoJSON定义的完整路径.
Defining the full path to the GeoJSON defintion within the array element.
然后查询正常工作:
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正在匹配文档",并且没有以任何方式指示匹配了哪个数组元素.
Which matches the document above. But of course there are multiple objects in the array, so the question is, which of these matched? To which there is no supported answer, as MongoDB is matching the "document" and not indicating in any way which array element was matched.
集合 $geoNear
中有一个选项确实允许返回匹配的对象,在这种情况下,它将是最近的".有了这样的细节,然后就有可能使用该信息来匹配具有完整元数据的数组元素包含为最近"找到的元素,并提取该数据.但同样,它只是接近",并且永远不能从数组中返回多个结果.
There is an option in the aggregation $geoNear
that does allow the matched object to be returned, where in this case it would be "nearest". And with detail like that is is then possible to use that information to match which array element with full meta data contains the element that was found for "nearest" and extract that data. But again it is "near" only and can also never return more than one result from an array.
但是通常来讲,最好将单独的对象作为文档收集在自己的集合中,其中与不同对象的匹配只是文档的匹配.因此,使用上面的数组作为它自己的集合时,您只需对匹配的几何图形发出查询:
But generally speaking it is better to just but the separate objects as documents in their own collection, where the match to distinct object is just a matter of matching the document. So with the array above in it's own collection, you just issue the query for the matching geometry:
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]
]]
}
}
}
})
给出正确的对象,在这种情况下,形状与两个对象相交:
Which gives the correct object(s) as in this case the shape intersects both:
{
"_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
]
]]
}
}
因此,您可以使用数组,但只能真正匹配文档,而不能真正匹配匹配项中的单个数组成员,因此这将返回整个课程文档,您需要确定哪些成员符合条件在客户端代码中.
So you can use arrays but you can only really match document and not the individual array members that were part of the match, so this will return of course documents as a whole and you would need to work out which members matched the criteria in client code.
另一方面,您的几次查询尝试都试图将对象坐标数组分解"为各个元素.完全不支持此功能,因为该对象只能作为一个整体来处理,而不能作为其"Point"部分来处理.
On another note, several of your query attempts seek to "break up" the object coordinates array into individual elements. This is not supported at all as the object can only be dealt with as a whole and not as it's "Point" parts.
这篇关于地理空间查询对数组有效吗? ($ geoWithin,$ geoIntersects)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!