简体   繁体   中英

How to query all spatial trajectories that go from one region to another

Consider a mongo db where each document corresponds to a spatial trajectory. That is, there is a field that contains an array for each document. Each array is a sequence of latitude/longitude pairs representing a geographical trajectory. Given two geographical regions R1, R2 defined by geojson polygones, find all trajectories that intersect first R1 and second R2. Given the size of the db, computational time is highly important.

My first attempt works but does not consider direction. Moreover, it is extremely slow. I use an aggregate framework (regions gjs[i]). My current pipeline contains the following.

{"$match":{"location.lonlat":{'$geoIntersects':{'$geometry':gjs[0]}}}}, {"$match":{"location.lonlat":{'$geoIntersects':{'$geometry':gjs[1]}}}}

From the MongoDB manual :

$geoIntersects uses spherical geometry. $geoIntersects does not require a geospatial index. However, a geospatial index will improve query performance. Only the 2dsphere geospatial index supports $geoIntersects.

So you have a problem: your query works because $geoIntersects does not require an index but it is slow because there is no index. To speed it up, you must create a 2dsphere index because that is the only index (ie NOT a 2d index) used by $geoIntersects -- which unfortunately will not work on legacy arrays of coordinate points (your "trajectories").

My recommendation is to go full GeoJSON:

  1. Convert your location.lonlat array of points to GeoJSON LineString object, eg
{location: {
        "trajectory" : {
            "type" : "LineString",
            "coordinates" : [ [10,60] , [10,61] , [10,62] ]
        }
    },

You could do this with a non-destructive update to create a new field trajectory as a peer to lonlat in the location object. Note the use of the array form of update() that permits pipelines and thus the $location.lonlat array can be copied into the new field:

db.foo.update({}, [ {$set: {"location.trajectory": {type: "LineString", coordinates: "$location.lonlat"}}} ], {multi:true});

  1. Create a 2dsphere index on location.trajectory :
db.foo.createIndex({"location.trajectory":"2dsphere"});

Your queries will now be performant.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM