xaxa
xaxa

Reputation: 1159

Mongodb spatial query on array

I have a collection of points with their properties, and I track their location as they move with time, so a document is like:

{
    _id: 1,
    mass: 2,
    track: [
        {
            time: 0,
            loc: [0, 0]
        },
        {
            time: 1,
            loc: [0.2, 0.1]
        },
        ...
    ]
}

So there is not a single field for location, but an array...
Can I use mongodb's geospatial capabilities to find all points that happened to move near a particular point |[x,y] - [x0,y0]| < R? Can I add time to this query: t1 < t < t2, |[x,y] - [x0,y0]| < R?

Upvotes: 0

Views: 835

Answers (2)

John Petrone
John Petrone

Reputation: 27507

Yes, there is a special case for this when using a geospatial index with MongoDB - it's known as a Multilocation Document:

Multi-location Documents for 2d Indexes

New in version 2.0: Support for multiple locations in a document.

While 2d geospatial indexes do not support more than one set of coordinates in a document, you can use a multi-key index to index multiple coordinate pairs in a single document.

http://docs.mongodb.org/manual/core/geospatial-indexes/#GeospatialIndexing-MultilocationDocuments

There is support for several different schemas for multi-location - your data model appears to map well. You should be able to use the following ensure index command:

db.collectionname.ensureIndex( { "track.loc": "2d" } )

Regarding your queries, though, not certain you can do that in MongoDB with this schema. The problem is that you are in effect trying to compare array entries against each other (comparing the time fields to find one larger then another within the same array). You might try using the Aggregation framework, but there are significant limitations in it's use with Geospatial coordinates:

http://docs.mongodb.org/manual/reference/operator/aggregation/geoNear/

Right now this looks to me like some custom coding. And I'd take a close look at whether you might be better off storing each time/location pair as separate documents. For instance, you could grab the first time/location for a point, calculate the distance and then query to see if there are any time/location pairs for that point with a distance less than the one you just calculated.

Upvotes: 0

Malcolm Murdoch
Malcolm Murdoch

Reputation: 1085

Yes - this is exactly what mongodb can do well.

Firstly, you'll need to create a geospatial index - let Mongodb precalculate where stuff is.

db.mycollection.ensureIndex({'track.loc':'2D'})

More information here: http://docs.mongodb.org/manual/core/2d/

Then, to find somewhere near a certain place:

db.mycollection.findOne({'track.loc':{'$near':[x,y]}})

There's also options to do this within bounding areas etc.

If you want to do this in conjunction with the time filter:

db.mycollection.findOne({'track.loc':{'$near':[x,y]}, 'track.time':{$gt:10}})

This will find you the nearest point to x,y where the time is greater than 10.

Hope you're not violating anyone's privacy!

Upvotes: 1

Related Questions