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

Géospatial $proche de la valeur du champ de document actuel

Oui c'est possible. Vous utilisez simplement $geoNear Au lieu. Méfiez-vous des pièges et lisez attentivement.

En supposant que votre intention est de stocker un champ tel que "travelDistance" pour indiquer sur le document que de telles recherches doivent être "à l'intérieur" de cette distance fournie par rapport au point interrogé pour être valides. Ensuite, nous interrogeons et évaluons simplement la condition avec $redact :

db.collection.aggregate([
  { "$geoNear": {
    "near": { 
      "type": "Point",
      "coordinates": [x,y]
    },
    "spherical": true,
    "distanceField": "distance"
  }},
  { "$redact": {
    "$cond": {
      "if": { "$lte": [ "$distance", "$travelDistance" ] },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }}
])

Le seul problème est que $geoNear comme $near ne renverra qu'un certain nombre de documents "proches" en premier lieu. Vous pouvez ajuster cela avec les options, mais contrairement au formulaire de requête général, cela garantit essentiellement que les résultats éventuels renvoyés seront inférieurs aux nombres "les plus proches" spécifiés.

Tant que vous en êtes conscient, cela est parfaitement valable.

C'est en fait la manière générale de qualifier ce qui est "proche" dans un rayon.

Soyez également conscient de la "distance" en fonction de la façon dont vous avez stocké les coordonnées. En tant que paires de coordonnées héritées, les distances seront en radians que vous devrez probablement faire le calcul pour convertir en kilomètres ou en miles.

Si vous utilisez GeoJSON, les distances sont toujours considérées en mètres, comme format standard.

Toutes les notes de maths sont dans la documentation.

N.B Lire le $geoNear documentation avec soin. Des options comme "spherical" sont requis pour "2dsphere" index, tels que vous devriez avoir pour les coordonnées du monde réel. Aussi "limit" peut devoir être appliqué pour augmenter au-delà du résultat de document par défaut de 100, pour un ajustement supplémentaire.

Comme les commentaires mentionnent le spring mongo, alors voici fondamentalement la même chose faite pour cela :

Aggregation aggregation = newAggregation(
    new AggregationOperation() {
      @Override
      public DBObject toDBObject(AggregationOperationContext context) {
        return new BasicDBObject("$geoNear",
          new BasicDBObject(
            "near", new BasicDBObject(
              "type","Point")
              .append("coordinates", Arrays.asList(20,30))
            )
            .append("spherical",true)
            .append("distanceField","distance")
          );
        }
    },
    new AggregationOperation() {
      @Override
      public DBObject toDBObject(AggregationOperationContext context) {
        return new BasicDBObject("$redact",
          new BasicDBObject(
            "$cond", Arrays.asList(
               new BasicDBObject("$lte", Arrays.asList("$distance", "$travelDistance")),
               "$$KEEP",
               "$$PRUNE"
             )
          )
       );
     }
    }
);