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

Query MongoDb vicino/geometrico con distanza variabile

Non sarai in grado di farlo con una query normale poiché non puoi impostare dinamicamente la distanza per documento. A partire da MongoDB 2.4 puoi farlo con il framework di aggregazione poiché hanno aggiunto l'operatore geoNear all'inizio delle pipeline.

La prima fase sarà il geoNear che è molto simile al comando geonear. Come risultato otterremo anche la distanza dal punto specificato (10,10) al documento.

Nella seconda fase dovremo utilizzare l'operatore di progetto per aggiungere la differenza tra il campo MaximumDistance e la geoNear distance calcolata.

Infine, abbiniamo quei documenti che hanno un delta positivo ((max - distanza)> 0).

Ecco la pipeline che utilizza il driver Java asincrono classi di supporto di.

package example;

import static com.allanbank.mongodb.builder.AggregationProjectFields.include;
import static com.allanbank.mongodb.builder.QueryBuilder.where;
import static com.allanbank.mongodb.builder.expression.Expressions.field;
import static com.allanbank.mongodb.builder.expression.Expressions.set;
import static com.allanbank.mongodb.builder.expression.Expressions.subtract;

import com.allanbank.mongodb.bson.element.ArrayElement;
import com.allanbank.mongodb.builder.Aggregate;
import com.allanbank.mongodb.builder.AggregationGeoNear;
import com.allanbank.mongodb.builder.GeoJson;

public class AggregateGeoNear {
    public static void main(String[] args) {
        Aggregate aggregate = Aggregate
                .builder()
                .geoNear(
                        AggregationGeoNear.builder()
                                .location(GeoJson.p(10, 10))
                                .distanceField("distance"))
                .project(
                        include("name", "location", "maximumDistance"),
                        set("delta",
                                subtract(field("maximumDistance"),
                                        field("distance"))))
                .match(where("delta").greaterThanOrEqualTo(0)).build();

        System.out
                .println(new ArrayElement("pipeline", aggregate.getPipeline()));
    }
}

Ed ecco che viene creata la pipeline:

pipeline : [
  {
    '$geoNear' : {
      near : [
        10, 
        10
      ],
      distanceField : 'distance',
      spherical : false,
      uniqueDocs : true
    }
  }, 
  {
    '$project' : {
      name : 1,
      location : 1,
      maximumDistance : 1,
      delta : {
        '$subtract' : [
          '$maximumDistance', 
          '$distance'
        ]
      }
    }
  }, 
  {
    '$match' : {
      delta : { '$gte' : 0 }
    }
  }
]

HTH - Rob.

PS I builder precedenti utilizzano una versione preliminare della versione 1.2.0 del driver. Il codice sta esaminando la matrice di compilazione durante la digitazione e dovrebbe essere rilasciato entro venerdì 22 marzo 2013.