如何为mongo db模式定义一个圆?

时间:2015-07-13 08:42:53

标签: mongodb mongodb-query geospatial

我有以下代码来定义架构:

var mongoose=require('mongoose');
var Schema=mongoose.Schema;
var PostSchema=new Schema({
location:{type:Array,required:false,select:true}
})
PostSchema.index({location:'2dsphere'});

module.exports=mongoose.model('Post',PostSchema);

我想让位置字段看起来像一个圆圈(例如:位置:{loc:[纬度,经度],半径:半径})..我想查询从我的数据库中找到圆圈与多边形相交。感谢任何帮助:)

1 个答案:

答案 0 :(得分:4)

要对"geospatial query"有效,“位置”必须为经度,纬度顺序且不能包含任何其他坐标。

有效格式为

 { 
     "location": [long,lat]
 }

 {
    "location": { "lng": long, "lat": lat }
 }

或GeoJSON

 {
     "location": {
         "type": "Point",
         "coordinates": [long,lat]
     }
 }

另一个字段如“radius”是“另一个字段”而不能是同一个数组的一部分。

理想情况下遵循GeoJSON:

 {
     "location": {
         "type": "Point",
         "coordinates": [long,lat]
     },
     "radius": radius
 }

在mongoose模式定义中可以如下这样简单:

var geoSchema = new Schema({
    "location": {
        "type": String,
        "coordinates": []
    },
    "radius": Number
});

在真实“地球”坐标处理地理空间数据时,您的索引应为"2dsphere",您可以选择在架构上定义为:

geoSchema.index({ "location": "2dsphere" })

由于在支持的GeoJSON中没有对“Circle”对象的实际支持,因此建议将另一个字段保留为“radius”并存储“中心点”。

GeoJSON相对于其他“遗留坐标对”格式的“巨大”优势在于,当通过geoNear$geoNear从点返回“距离”之类的东西时,那么“距离”是始终以“米”定义。这也是您应该如何定义存储中的任何“半径”值以保持与该结果一致。

使用其他存储格式,结果将以“弧度”返回,您可能希望转换该结果,并且不希望存储圆的“半径”,并将其作为度量。

处理这个问题的方法是,考虑这种形式的数据:

{
    "locationtype": "circle",
    "location": {
        "type": "Point",
        "coordinates": [1,1]
    },
    "radius": 4
}

然后您使用.aggregate() $geoNear阶段和$redact进行过滤:

db.collection.aggregate([
    // Find points or objects "near" and project the distance
    { "$geoNear": {
        "near": {
            "type": "Point",
            "coordinates": [2,2]
        },
        "distanceField": "distance",
        "query": { "locationType": "circle" }
    }},
    // Logically filter anything outside of the radius
    { "$redact": {
        "$cond": {
            "if": { "$gt": [ "$distance", "$radius" ] },
            "then": "$$PRUNE",
            "else": "$$KEEP"
        }
    }}
])

现在查询示例中使用的值只是一个示例,但正如“真实”经度和纬度坐标所述,“距离”属性按设计工作,并且在前面提到的“米”公差范围内。

这里的要点是$geoNear无论对象类型是什么,都会在“圆圈”中心找到“附近”。不仅如此,而且这里的命令正在生成文档中另一个字段的“投影”,如“distanceField”中所述。这表示与“米”中的圆“中心”的距离。

此处的第二阶段使用$redact,因为它有点像$project$match管道阶段。与$match不同,此运算符可以通过比较文档中存在的字段来评估“逻辑”条件。在这种情况下,$$PRUNE之类的操作会将匹配的文档移除到“if”条件,其中true并从结果中“删除”它,或者$$KEEP条件为{{1}的文档}}

在“简言之”中,如果“距离”是“大于”,那么“圆圈”的“半径”则物体“位于圆圈外”并且不“相交”。否则“它确实”。

这就是“为集合中的几何定义'圆''和”使用它“来实现类似”圆“半径内”点“或其他类型对象之间交点的基础。