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

Geodaten $near innerhalb des aktuellen Dokumentfeldwerts

Ja es ist möglich. Sie verwenden einfach $geoNear stattdessen. Achten Sie auf die Fänge und lesen Sie sorgfältig.

Angenommen, Sie möchten ein Feld wie "travelDistance" speichern um auf dem Dokument anzugeben, dass solche Suchen "innerhalb" dieser angegebenen Entfernung vom abgefragten Punkt sein müssen, um gültig zu sein. Dann fragen wir die Bedingung einfach mit $redact ab und werten sie aus :

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

Der einzige Haken ist, dass $geoNear genau wie $near wird zunächst nur eine bestimmte Anzahl von Dokumenten "in der Nähe" zurückgeben. Sie können dies mit den Optionen einstellen, aber im Gegensatz zum allgemeinen Abfrageformular garantiert dies im Grunde, dass die letztendlich zurückgegebenen Ergebnisse kleiner als die angegebenen "nächsten" Zahlen sein werden.

Solange Sie sich dessen bewusst sind, ist dies vollkommen gültig.

Es ist in der Tat die allgemeine Art, mit der Qualifizierung dessen umzugehen, was innerhalb eines Radius "nah" ist.

Beachten Sie auch die "Entfernung", je nachdem, wie Sie die Koordinaten gespeichert haben. Als Legacy-Koordinatenpaare werden die Entfernungen in Radianten angegeben, die Sie wahrscheinlich rechnen müssen, um sie in Kilometer oder Meilen umzurechnen.

Wenn Sie GeoJSON verwenden, werden die Entfernungen immer in Metern als Standardformat berücksichtigt.

Alle mathematischen Anmerkungen sind in der Dokumentation.

NB Lesen Sie den $geoNear Dokumentation sorgfältig. Optionen wie "spherical" werden für "2dsphere" benötigt Indizes, wie Sie sie für reale Koordinaten haben sollten. Auch "limit" muss möglicherweise angewendet werden, um das standardmäßige Ergebnis von 100 Dokumenten zu erhöhen und weiter zuzuschneiden.

Da in den Kommentaren Frühlingsmongo erwähnt wird, wird hier im Grunde dasselbe getan:

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