MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Geospaziale $ vicino al valore del campo del documento corrente

Si è possibile. Devi solo usare $geoNear invece. Attenti ai fermi e leggete attentamente.

Presumendo che la tua intenzione sia quella di memorizzare un campo come "travelDistance" indicare sul documento che tali ricerche devono essere "entro" la distanza fornita dal punto interrogato per essere valide. Quindi interroghiamo e valutiamo semplicemente la condizione con $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"
    }
  }}
])

L'unico problema è che $geoNear proprio come $near restituirà solo un certo numero di documenti "vicino" in primo luogo. Puoi ottimizzarlo con le opzioni, ma a differenza del modulo di query generale, ciò garantisce sostanzialmente che gli eventuali risultati restituiti saranno inferiori ai numeri "più vicini" specificati.

Finché ne sei consapevole, questo è perfettamente valido.

È infatti il ​​modo generale di gestire la qualificazione di ciò che è "vicino" all'interno di un raggio.

Tieni anche presente la "distanza" in base a come hai memorizzato le coordinate. Come coppie di coordinate legacy, le distanze saranno in radianti che probabilmente dovrai fare i calcoli per convertire in chilometri o miglia.

Se si utilizza GeoJSON, le distanze sono sempre considerate in metri, come formato standard.

Tutte le note di matematica sono nella documentazione.

NB Leggi il $geoNear documentazione con attenzione. Opzioni come "spherical" sono richiesti per "2dsphere" indici, come dovresti avere per le coordinate del mondo reale. Anche "limit" potrebbe essere necessario applicare per aumentare oltre il risultato predefinito di 100 documenti, per un ulteriore ritaglio.

Poiché i commenti menzionano il mongo primaverile, qui è praticamente la stessa cosa fatta per quello:

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