Chris
Chris

Reputation: 7853

How to dynamically filter datasets based on their location

I'm trying to achieve the following behaviour with a mongodb query:

The query currently looks like this:

query["location"] = {
     $nearSphere: {
      $geometry: user.gps,
      $maxDistance: filterDistance
    }
};

This query successfully selects all the datasets in a given filterDistance relative to the user.

What i'd like to have now is "If document.maxdistance field > 0 and the distance to the user is greater than document.maxdistance" do not select the dataset.

So i have documents that should not be found if the user lives in a distance greater than a given distance saved inside the document.

I don't know hot to express this in a mongodb query and i couldn't find any example of such a query.

Upvotes: 0

Views: 161

Answers (1)

Alex Blex
Alex Blex

Reputation: 37048

$near/$nearSphere don't support per-document distance. Only per query. The main reason is sorting by distance. If you need only filtering you can use $geoIntersects/$geoWithin, but you will need to change documents to contain a polygon of the covered area, like a circle Pi*2*distance around it's location.

Example:

Assuming you have a document:

{
    loc: { type: "Point", coordinates: [ 10, 20 ] },
    distance: 10
}

So that it is returned when user's coordinate is within the radius, e.g. [12, 25], and is not returned when user's coordinate is outside, e.g. [12,30].

For that documents should be updated to convert loc/distance pair to a polygon. For the sake of simplicity I'll use octagon, but you may want to increase number of vertices for more accurate results:

{
    loc: { type: "Point", coordinates: [ 10, 20 ] },
    distance: 10,
    area: {
        type : "Polygon",
        coordinates : [[ 
            [ 17, 27 ], 
            [ 10, 30 ], 
            [ 3, 27 ], 
            [ 0, 20 ], 
            [ 3, 13 ], 
            [ 10, 10 ], 
            [ 17, 13 ], 
            [ 20, 20 ], 
            [ 17, 27 ] 
        ]]
    }
}

Then you can use $geoIntersects to find documents which area includes user's coordinates:

db.collection.find({
    area: {
        $geoIntersects: {
            $geometry: { type: "Point" , coordinates: [ 12, 25] }
        }
    }
})    

Upvotes: 1

Related Questions