在mongodb地理位置查询中使用对象属性作为$ maxDistance参数 [英] Using an object property as the $maxDistance argument in a mongodb geolocation query
问题描述
我想用$ maxDistance参数编写一个$ near查询,其值不是常量。例如,我收集了一系列具有地理位置和覆盖半径的消防站,并且我希望找到覆盖半径包含某些特定点的所有消防站。
我收集的文件看起来像这样:
{
'loc':[-72,40],
'radius':10
}
一个类似如下的查询:
{' loc':{$ near:coordinates,$ maxDistance:'radius'}};
但这是不正确的。
如果我正在编写SQL查询,我会使用类似于:
SELECT * FROM表AS foo WHERE foo.radius。 ..(无论你的距离方法如何)
但我无法弄清楚如何访问mongo查询中的半径变量。这甚至有可能吗?
你不能这样做 - 总的来说,你不能在MongoDB中创建任何东西查询集合中的值。然而,自MongoDB 2.4以来,我们支持一个名为 2dsphere
的新索引,它允许您不仅存储数据库,但多边形也是如此。您可以将这些信息存储在如下文档中:
db.so.ensureIndex({loc:'2dsphere'});
db.so.insert({
名称:Firestation 1,
loc:{
类型:Polygon,
coordinates:[[[0, 0],[0,1],[1,1],[1,0],[0,0]]]
}
});
然后您可以使用相交查询来计算每个点是否覆盖多边形:
db.so.find({
'loc':{
$ geoIntersects: {
$ geometry:{type:'Point',coordinates:[0,0]}
}
}
});
然后返回:
{
_id:ObjectId(51f24d566775068ab0b786f0),
name:Firestation 1,
loc:{
键入:Polygon,
coordinates:[[[0,0],[0,1],[1,1],[1,0],[0,0]]]
$ b在这里找到消防站,因为0,0是在多边形的中间。现在诀窍是计算构成距离中心点半径(比如说10公里)的圆的多边形点。你将无法获得真正的圈子,但六角形或八角形应该足够好。数学并不是非常简单,但 http:// www。 movable-type.co.uk/scripts/latlong.html#destPoint 在JavaScript中有一个例子。
只需循环8次,从0到2PI,计算圆周上的点,并将它们放在坐标中。确保将它们嵌入到双重嵌套数组中,并使第一个和最后一个相同:
{
名称:Firestation 1,
loc:{
类型:Polygon,
坐标:[[
[point1-lon,point1-lat],
[point2-lon,point2-lat],
[point3-lon,point3-lat],
...
[point1-lon,point1-lat],
] ]
}
}
I would like to write a $near query with a $maxDistance argument whose value is not constant. For example, I have a collection of fire stations with a location and a coverage radius, and I want to find all fire stations whose coverage radius includes some specific point. The coverage radius can vary by station.
I have a collection full of documents that look like:
{
'loc' : [-72,40],
'radius' : 10
}
A query that looks something like:
{'loc': { $near : coordinates, $maxDistance : 'radius'}};
But that isn't correct.
If I were writing a SQL query, I would use something like:
SELECT * FROM table AS foo WHERE foo.radius ... (whatever your distance method looks like)
But I can't figure out how to access that radius variable in a mongo query. Is this even possible?
解决方案 You can't quite do this like this — in general you can not base anything in your MongoDB queries on values in the collections.
However, since MongoDB 2.4 we support a new index called 2dsphere
which allows you to store not only points in the database, but polygons as well. You'd store that information in a document like:
db.so.ensureIndex( { loc: '2dsphere' } );
db.so.insert( {
name: "Firestation 1",
loc: {
type: "Polygon",
coordinates: [ [ [ 0, 0 ], [ 0, 1 ], [ 1, 1 ], [ 1, 0 ], [ 0, 0 ] ] ]
}
} );
And then you can use an "intersect" query to figure out whether a point is covered by each of the polygons:
db.so.find( {
'loc' : {
$geoIntersects: {
$geometry: { type: 'Point', coordinates: [ 0, 0 ] }
}
}
} );
Which then returns:
{
"_id" : ObjectId("51f24d566775068ab0b786f0"),
"name" : "Firestation 1",
"loc" : {
"type" : "Polygon",
"coordinates" : [ [ [ 0, 0 ], [ 0, 1 ], [ 1, 1 ], [ 1, 0 ], [ 0, 0 ] ] ]
}
}
Here it finds the fire station, because 0, 0 is in the middle of the polygon. Now the trick is of course to calculate the polygon points that make up a circle that is "radius" (say 10km) away from the centre point. You won't be able to get a real circle, but a hexagon or octagon should be good enough. The maths for that isn't extremely simple, but http://www.movable-type.co.uk/scripts/latlong.html#destPoint has an example in JavaScript.
Just loop your bearing in 8 steps from 0 to 2PI to calculate the points along the circumference of the circle, and put those in the coordinates. Make sure to embed them in a doubly nested array and make the first and the last one the same:
{
name: "Firestation 1",
loc: {
type: "Polygon",
coordinates: [ [
[ point1-lon, point1-lat ],
[ point2-lon, point2-lat ],
[ point3-lon, point3-lat ],
...
[ point1-lon, point1-lat ],
] ]
}
}
这篇关于在mongodb地理位置查询中使用对象属性作为$ maxDistance参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!