在 GeoJson MultiLineString 中查询哪个 LineString
Posted
技术标签:
【中文标题】在 GeoJson MultiLineString 中查询哪个 LineString【英文标题】:Query which LineString in GeoJson MultiLineString 【发布时间】:2015-09-08 03:52:54 【问题描述】:鉴于我有一条由 2 个主要巴士站组成的公共巴士路线。路由分为2条子路由,循环互连,但路由编号相同。
所以我将 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
,第一条或第二条。
是否有可能,如果可以,是否有可能在一个查询中获得附近的路线和子路线?
【问题讨论】:
【参考方案1】: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
来提取所需的元素。所以第一种情况是从$geoNear
中提取“includeLocs”返回中已经识别的匹配元素。然后,这允许您重新处理数组并仅过滤掉包含相同“类型”的“元素”用于路线的腿,并且为了增加美观性,我们还标记了数组成员实际上是“最近”匹配的时间。
特别是与要匹配的路由“类型”,早先$map
返回的变量实际上是一个数组。所以你只能真正将一个数组与另一个“数组”进行比较,这就是为什么$map
再次用于单个字段值,以便将其变成一个数组本身:
"$setEquals": [
"$map": "input": ["A"], "as": "el", "in": "$$stop.type" ,
"$$matchedStop.type"
],
这就是该部分的全部内容,当然$setEquals
会测试两个数组以查看它们是否实际上相同。
这里的其他内容是$let
,以便让“matchedStop”更易于访问,$setDifference
实质上从通过对数组成员进行的测试中过滤掉false
的任何返回值$cond
运营商。
当然,这里的替代方案基本上只是将每个“站点”分离到集合中它自己的文档中,然后运行一个查询以查找“最近”文档,并运行另一个查询以查找相同的“路线”和其他在您的返回信息中停在该路线的同一“腿”上。但这仍然会被包含在一个文档和匹配中,并且非常有效,尤其是对于多个“路由”匹配。
【讨论】:
好的,差不多了,但我确实有停靠点之间的航路点数据,这可能会改善“附近”的结果。因此,似乎我需要更新新结构以将索引stops.waypoints
包含为LineString
以供$geoNear
使用,同时保持stops.location
Point
未编入索引以供$project
使用,对吗?
@CallMeLaNN 我不能为你编写你的项目,但只是告诉你什么不能工作,什么可以工作。不可能将“LineString”用于您的目的,因为您希望每个“节点”作为您需要专门匹配的位置。这就是答案向您展示的内容。
我现在明白我无法从MultiLineString
和LineString
中提取Point
。由于在两个站点之间提取最小的LineString
是可以接受的,不是说每个节点,应该没问题,我可以得到哪个“子路线”和“站点”。 +1 提及聚合框架。谢谢你的时间。
@CallMeLaNN LineString 可能对您不起作用,因为您仍然无法识别离您最近的“停止”。 $geoNear
在此处聚合的唯一好处是内容是如上所示的“数组”,然后您可以匹配最近点的“数组条目”。否则使用文档。但是您无法从MultiLineString
或LineString
中获取该数据。因此教训。
从你的例子中得到想法后,让我澄清一下我的想法。这里的LineString
指的是停靠点之间的航路点,而不是停靠点列表。我将查询哪个站点,而不是单个航路点“节点”。我遵循与您建议相同的方式:一系列停靠点包含一个位置Point
,但我添加了航点LineString
。让我试试看。最坏的情况是我将创建另一个包含多个查询的文档。以上是关于在 GeoJson MultiLineString 中查询哪个 LineString的主要内容,如果未能解决你的问题,请参考以下文章
访问与 LINESTRING M 和 MULTILINESTRING M 几何相关的 M 值
是否可以使用 JavaScript 确定 GeoJSON 点是否在 GeoJSON 多边形内?
python 在Python中将GeoJSON转换为WKT或从WKT转换。 #python #geojson #geometry