Find a Location withing a stored Circle

2019-01-26 01:08发布

问题:

I have data in MongoDB representing a Circle as follows:

{
    "_id" : ObjectId("54c1dc6506a4344d697f7675"),
    "location" : [ 
        23.027573, 
        72.50675800000001
    ],
    "radius" : 500
}

I want to query with lat & long to determine whether the location is withing stored lat&long and radius.

I tried following query but unable to execute:

db.test.find({location:{ $geoWithin: { $center: [ [ -74, 40.74 ] ,
                                                         "$radius"] } }})

How can we used stored radius in geoWithin query?

回答1:

Actually a little more optimal than when first written. Now we can just $redact rather than $project the boolean and $match later:

db.collection.aggregate([
    // Match documents "near" the queried point
    { "$geoNear": {
        "near": {
            "type": "Point",
            "coordinates": [ 23.027573, 72.50675800000001 ],
        },
        "distanceField": "distance"
    }},

    // Calculate if distance is within radius and remove if not
    { "$redact": {
        "$cond": {
            "if": { "$lte": [ "$distance", "$radius" ] },
            "then": "$$KEEP",
            "else": "$$PRUNE"
        }
    }}
])

You've stored the information exactly how you should, but there is a different approach to getting the results than you think.

What you want to use is a $geoNear and specifically the aggregation framework form of that operator. Here's what you do:

db.collection.aggregate([
    // Match documents "near" the queried point
    { "$geoNear": {
        "near": {
            "type": "Point",
            "coordinates": [ 23.027573, 72.50675800000001 ],
        },
        "distanceField": "distance"
    }},

    // Calculate if distance is within radius
    { "$project": {
        "location": 1,
        "radius": 1,
        "distance": 1,
        "within": { "$lte": [ "$distance", "$radius" ] }
    }},

    // Match only documents within the radius
    { "$match": { "within": true } }
])

So that form allows the distance from the queried point to be "projected" in the results, whilst the query will also only return the nearest documents.

Then you use a logical comparison to see if the "distance" value is less than "radius", therefore within the circle.

Finally you match to filter out only those results where that "within" assertion was true.

You can add other options to $geoNear as shown in the documentation. I would also strongly suggest that your storage should also use the GeoJSON format as that is likely to be more compatible to whatever other libraries you might use to work on the results obtained.



回答2:

MongoDB provides strong support for GEO based query. To check whether your location is within the centre you mentioned, there is a $geoNear.