MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

MongoDb Near/Geonear-Abfrage mit variabler Entfernung

Mit einer normalen Abfrage ist dies nicht möglich, da Sie die Entfernung pro Dokument nicht dynamisch festlegen können. Ab MongoDB 2.4 können Sie dies mit dem Aggregation Framework tun, da sie den geoNear-Operator zu den Anfängen von Pipelines hinzugefügt haben.

Die erste Stufe wird der Befehl geoNear sein, der dem Befehl geonear sehr ähnlich ist. Als Ergebnis erhalten wir auch die Entfernung vom angegebenen Punkt (10,10) zum Dokument.

In der zweiten Phase müssen wir den Projektoperator verwenden, um den Unterschied zwischen dem MaximumDistance-Feld und der berechneten geoNear-Entfernung hinzuzufügen.

Zuletzt gleichen wir die Dokumente ab, die ein positives Delta haben ((max - Distanz)> 0).

Hier ist die Pipeline, die den asynchroner Java-Treiber verwendet Hilfsklassen von .

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

Und hier wird die Pipeline erstellt:

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.

P.S. Die obigen Ersteller verwenden eine Vorabversion der Version 1.2.0 des Treibers. Der Code durchläuft die Build-Matrix, während ich tippe, und sollte bis Freitag, den 22. März 2013 veröffentlicht werden.