如何为mongo db模式定义一个圆? [英] How to define a circle for a mongo db schema?

查看:72
本文介绍了如何为mongo db模式定义一个圆?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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);

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

解决方案

要对地理空间查询" 有效,位置"必须按经度,纬度的顺序进行,并且不能包含任何其他坐标.

有效格式为

  { 
     "location": [long,lat]
 }
 

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

或GeoJSON

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

另一个字段(例如半径")是另一个字段",并且不能成为同一数组的一部分.

理想地遵循GeoJSON:

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

猫鼬模式定义中的内容可以很简单:

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

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

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

由于受支持的GeoJSON中没有对圆"对象的实际支持,因此建议将另一个字段保留为半径"并存储中心点".

与其他传统坐标对"格式相比,GeoJSON的大"优势在于,通过

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

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

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

然后,将 .aggregate() 与<一个href ="http://docs.mongodb.org/manual/reference/operator/aggregation/geoNear/" rel ="nofollow"> $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并将其从结果中删除",否则


这就是定义集合中的几何图形的圆"并使用它"以实现圆"半径内的点"或其他类型的对象之间的交集的基本知识." >

I have the folowing code to define a schema:

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);

I want to make location field to be seen like a circle(ex:location:{loc:[latitude,longitude],radius:radius})..I want to make a query to find circles form my db which are intersecting with a polygon.Thanks for any help :)

解决方案

To be valid for a "geospatial query" the "location" must be in longitude, latitude order and cannot contain any other coordinates.

Valid formats are

 { 
     "location": [long,lat]
 }

Or

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

Or GeoJSON

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

Another field such as "radius" is "another field" and cannot be part of the same array.

Ideally follow GeoJSON:

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

Which in mongoose schema definition can be as simple as:

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

When dealing with geospatial data at real "globe" coordinates your index should be "2dsphere", which you optionally define on the schema as :

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

Since there is no actual support for a "Circle" object in supported GeoJSON then keeping another field as "radius" and storing the "center point" is recommended.

The "big" advantage with GeoJSON over the other "legacy coordinate pairs" formats is that when returning something like a "distance" from a point via geoNear or $geoNear then that "distance" is defined in "meters" consistently. This is also how you should be defining any "radius" value in your storage to remain consistent with that result.

With the other storage formats then the result is returned in "radians", for which you probably want to convert and would prefer not to be storing a "radius" of a circle with that as a measurement.

The way you deal with this is, considering data in this form:

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

Then you use .aggregate() with a $geoNear stage and a $redact to filter:

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"
        }
    }}
])

Now the values used in the query example are just an example, but as stated with "real" longitude and latitude coordinates the "distance" attributes work out as designed and within the "meters" tolerance as mentioned earlier.

The points here are that $geoNear will both find "near" to the "circle" center poiny no matter what the object type. Not only that but the command here is producing a "projection" of another field in the document here as named in "distanceField". This represents the distance from the circle "center" in "meters".

The second stage here uses $redact since it is sort of like a $project and $match pipeline stage in one. Unlike $match this operator can evaluate a "logical" condition by comparing fields present in the document. In this case, operations like $$PRUNE remove the matched document to the "if" condition where true and "remove" it from results or otherwise $$KEEP the document where the condition was false.

In a "nutshell", if "distance" is "greater than" then "radius" of the "circle" then the object "lies outside" of the circle and does not "intersect". Otherwise "it does".


So that is the basics of "defining a 'circle' for geometry in a collection and "using it" to achieve something like the intersection between a "Point" or other type of Object within the "circle" radius.

这篇关于如何为mongo db模式定义一个圆?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆