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

onn*_*ner 0 geospatial mongodb mongodb-query

我有以下代码来定义模式:

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

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

我想使位置字段看起来像一个圆(例如:location:{loc:[latitude,longitude],radius:radius})。感谢您的帮助:)

Bla*_*ven 5

为了对“地理空间查询”有效,“位置”必须采用经度,纬度顺序,并且不能包含任何其他坐标。

有效格式为

 { 
     "location": [long,lat]
 }
Run Code Online (Sandbox Code Playgroud)

要么

 {
    "location": { "lng": long, "lat": lat }
 }
Run Code Online (Sandbox Code Playgroud)

或GeoJSON

 {
     "location": {
         "type": "Point",
         "coordinates": [long,lat]
     }
 }
Run Code Online (Sandbox Code Playgroud)

另一个字段(例如“ radius”)是“另一个字段”,并且不能是同一数组的一部分。

理想情况下,遵循GeoJSON:

 {
     "location": {
         "type": "Point",
         "coordinates": [long,lat]
     },
     "radius": radius
 }
Run Code Online (Sandbox Code Playgroud)

猫鼬模式定义中的哪一个可以很简单:

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

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

geoSchema.index({ "location": "2dsphere" })
Run Code Online (Sandbox Code Playgroud)

由于在受支持的GeoJSON中不实际支持“圆”对象,因此建议将另一个字段保留为“半径”并存储“中心点”。

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

对于其他存储格式,结果将以“弧度”返回,您可能要对其进行转换,并且不希望将圆的“半径”作为度量来存储。

处理此问题的方法是,考虑以下形式的数据:

{
    "locationtype": "circle",
    "location": {
        "type": "Point",
        "coordinates": [1,1]
    },
    "radius": 4
}
Run Code Online (Sandbox Code Playgroud)

然后,使用.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"
        }
    }}
])
Run Code Online (Sandbox Code Playgroud)

现在,查询示例中使用的值仅是一个示例,但是如使用“真实”经度和纬度坐标所说明的那样,“距离”属性按设计工作并且在如前所述的“米”公差内。

$geoNear无论对象类型如何,这里的要点都是都将在“圆”中心点附近。不仅如此,这里的命令还在此处以“ distanceField”命名的文档中生成另一个字段的“投影”。这表示距圆“中心”的距离(以“米”为单位)。

这里使用第二阶段,$redact因为它有点像a $project$match管道阶段中的一个。与$match该操作员不同,该操作员可以通过比较文档中存在的字段来评估“逻辑”条件。在这种情况下,诸如$$PRUNE将匹配的文档移至条件为的“ if”条件,true然后从结果或$$KEEP条件为条件的文档中“删除”它的操作false

在“简而言之”中,如果“距离”“大于”,则“圆”的“半径”,则对象“位于圆的外部”并且不“相交”。否则“确实如此”。


因此,这是“定义集合中的几何图形的“圆”并“使用它”以实现“圆”半径内的“点”或其他类型的对象之间的交集)的基础。