因为我有一条由两个主要巴士站组成的公共巴士路线。该路由分为两个子路由,相互连接成圆形,但两者的路由号相同。
因此,我将routes存储在GeoJson MultiLineString中(在GeoJson中包含2 LineStrings )。route文档看起来类似于:
{
"routeName": "A123",
"route": {
"type": "MultiLineString",
"coordinates": [
[ [100.0, 0.0], [101.0, 1.0], [102.0, 2.0] ],// 1st sub route
[ [102.0, 2.0], [103.0, 3.0], [100.0, 0.0] ] // 2nd sub route
]
}
}现在,如果使用$near进行查询,我可以得到最接近的route文档。然而,我想知道最近的子路线或LineString,或者是第一条还是第二条。
是否有可能,如果有,是否有可能在一个查询中获得附近的路由和子路由?
发布于 2015-09-08 05:58:48
MongoDB不能像您想做的那样,为了匹配“最近的点”而“拆分”GeoJSON对象。因此,您的问题很可能更适合于另一种结构,即将每个“停止”分配给独立考虑,而不是仅仅将其表示为"LineString“上的一个点。
在查询中使用此方法的一个非常有效的方法是:
{
"routename": "A123",
"stops": [
{
"type": "out",
"location": {
"type": "Point",
"coordinates": [100.0,0.0]
}
},
{
"type": "out",
"location": {
"type": "Point",
"coordinates": [101.0,1.0]
}
},
{
"type": "return",
"location": {
"type": "Point",
"coordinates": [102.0,2.0]
}
},
{
"type": "return",
"location": {
"type": "Point",
"coordinates": [103.0,3.0]
}
}
]
}它将路线上的每个“站”分解为一个不同的“点”,并保持路线“类型”,表示该站是在“出”段还是“返回”段。
然后,您可以使用$geoNear运行这个聚合查询,以便匹配和投影数组条目中的“最近点”。下一阶段将匹配的位置与数组中的每个“停止”进行比较,以便提取该停止所属的路线的支路:
db.routes.aggregate([
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [103.0, 2.0]
},
"distanceField": "distance",
"spherical": true,
"includeLocs": "loc"
}},
{ "$project": {
"routeName": 1,
"distance": 1,
"route": {
"$let": {
"vars": {
"matchedStop": {
"$setDifference": [
{ "$map": {
"input": "$stops",
"as": "stop",
"in": {
"$cond": [
{ "$eq": [ "$$stop.location", "$loc" ] },
"$$stop",
false
]
}
}},
[false]
]
}
},
"in": {
"$setDifference": [
{ "$map": {
"input": "$stops",
"as": "stop",
"in": {
"$cond": [
{ "$setEquals": [
{ "$map": { "input": ["A"], "as": "el", "in": "$$stop.type" } },
"$$matchedStop.type"
]},
{
"type": "$$stop.type",
"location": "$$stop.location",
"nearest": {
"$eq": [ "$$stop.location", "$loc" ]
}
},
false
]
}
}},
[false]
]
}
}
}
}}
])这将为您提供这种类型的输出:
{
"_id" : ObjectId("55ee6c0a2343a0d2e1650e28"),
"distance" : 111251.03086891436,
"route" : [
{
"type" : "return",
"location" : {
"type" : "Point",
"coordinates" : [
102,
2
]
},
"nearest" : true
},
{
"type" : "return",
"location" : {
"type" : "Point",
"coordinates" : [
103,
3
]
},
"nearest" : false
}
]
}这主要是为了提取所需的元素而大量使用$map。因此,第一种情况是提取在"includeLocs“返回的”$geoNear“中标识的匹配元素。这样,您就可以重新处理数组,并且只筛选出包含相同“类型”的“元素”,这些元素用于路由的分支,并且为了增加的良好性,我们还可以在数组成员实际上是“最近的”匹配时标记它。
特别是对于要匹配的路由"type“,来自早期$map的返回变量实际上是一个数组。因此,您只能将数组与另一个“数组”进行实际比较,这就是为什么$map再次用于奇异字段值,以便将其转换为数组本身:
{ "$setEquals": [
{ "$map": { "input": ["A"], "as": "el", "in": "$$stop.type" } },
"$$matchedStop.type"
]},这就是这个部分的意义所在,当然,$setEquals会测试两个数组,看看它们是否实际上是相同的。
这里的其他功能是$let,以使获取"matchedStop“更容易访问,而$setDifference实际上是从正在通过$cond操作符对数组成员进行的测试中筛选出false的任何返回值。
当然,这里的替代方法基本上是将每个"stop“分离到集合中它自己的文档中,然后运行一个查询来查找”最近的“文档,然后再运行另一个查询,在返回信息中找到相同的”路由“和在该路线的同一”路径“上的其他站点。但是,这仍然是自我包含在一个文档和匹配中,并且非常有效,特别是对于多个“路由”匹配。
https://stackoverflow.com/questions/32449009
复制相似问题