Find a Location within a stored Circle

前端 未结 2 1645
离开以前
离开以前 2021-01-01 05:51

I have data in MongoDB representing a Circle as follows:

{
    \"_id\" : ObjectId(\"54c1dc6506a4344d697f7675\"),
    \"location\" : [ 
        23.027573, 
           


        
相关标签:
2条回答
  • 2021-01-01 06:39

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

    0 讨论(0)
  • 2021-01-01 06:47

    Even more optimal than the original, you can now use $expr within a $match stage after the initial $geoNear:

    db.collection.aggregate([
        { "$geoNear": {
            "near": {
                "type": "Point",
                "coordinates": [ 23.027573, 72.50675800000001 ],
            },
            "distanceField": "distance"
        }},
        { "$match": { "$expr": { "$lte": [ "$distance", "$radius" ] } }}
    ])
    

    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.

    0 讨论(0)
提交回复
热议问题