MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Trouver une position dans un cercle enregistré

Encore plus optimal que l'original, vous pouvez désormais utiliser $expr dans un $match étape après le premier $geoNear :

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

En fait, un peu plus optimal que lors de la première écriture. Maintenant, nous pouvons simplement $redact plutôt que $project le booléen et $match plus tard :

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"
        }
    }}
])

Vous avez stocké les informations exactement comme vous le devriez, mais l'approche pour obtenir les résultats est différente de celle que vous pensez.

Ce que vous voulez utiliser est un $geoNear et plus précisément le framework d'agrégation forme de cet opérateur. Voici ce que vous faites :

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 } }
])

Ainsi, cette forme permet de "projeter" la distance depuis le point interrogé dans les résultats, tandis que la requête ne renverra également que les documents les plus proches.

Ensuite, vous utilisez une comparaison logique pour voir si la valeur "distance" est inférieure à "rayon", donc à l'intérieur du cercle.

Enfin, vous faites correspondre pour filtrer uniquement les résultats où cette affirmation "dans" était vraie.

Vous pouvez ajouter d'autres options à $geoNear comme indiqué dans la documentation. Je suggérerais également fortement que votre stockage utilise également le format GeoJSON car il est susceptible d'être plus compatible avec les autres bibliothèques que vous pourriez utiliser pour travailler sur les résultats obtenus.