首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >LineString在GeoJson MultiLineString中的查询

LineString在GeoJson MultiLineString中的查询
EN

Stack Overflow用户
提问于 2015-09-08 03:52:54
回答 1查看 757关注 0票数 1

因为我有一条由两个主要巴士站组成的公共巴士路线。该路由分为两个子路由,相互连接成圆形,但两者的路由号相同。

因此,我将routes存储在GeoJson MultiLineString中(在GeoJson中包含2 LineStrings )。route文档看起来类似于:

代码语言:javascript
复制
{
  "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,或者是第一条还是第二条。

是否有可能,如果有,是否有可能在一个查询中获得附近的路由和子路由?

EN

回答 1

Stack Overflow用户

发布于 2015-09-08 05:58:48

MongoDB不能像您想做的那样,为了匹配“最近的点”而“拆分”GeoJSON对象。因此,您的问题很可能更适合于另一种结构,即将每个“停止”分配给独立考虑,而不是仅仅将其表示为"LineString“上的一个点。

在查询中使用此方法的一个非常有效的方法是:

代码语言:javascript
复制
{
  "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运行这个聚合查询,以便匹配和投影数组条目中的“最近点”。下一阶段将匹配的位置与数组中的每个“停止”进行比较,以便提取该停止所属的路线的支路:

代码语言:javascript
复制
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]
          ]
        }
      }
    }
  }}
])

这将为您提供这种类型的输出:

代码语言:javascript
复制
{
    "_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再次用于奇异字段值,以便将其转换为数组本身:

代码语言:javascript
复制
{ "$setEquals": [
  { "$map": { "input": ["A"], "as": "el", "in": "$$stop.type" } },
  "$$matchedStop.type"
]},

这就是这个部分的意义所在,当然,$setEquals会测试两个数组,看看它们是否实际上是相同的。

这里的其他功能是$let,以使获取"matchedStop“更容易访问,而$setDifference实际上是从正在通过$cond操作符对数组成员进行的测试中筛选出false的任何返回值。

当然,这里的替代方法基本上是将每个"stop“分离到集合中它自己的文档中,然后运行一个查询来查找”最近的“文档,然后再运行另一个查询,在返回信息中找到相同的”路由“和在该路线的同一”路径“上的其他站点。但是,这仍然是自我包含在一个文档和匹配中,并且非常有效,特别是对于多个“路由”匹配。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32449009

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档