2016-04-18 4 views
2

Ich erstelle ein passendes System, das auf der Nähe des Benutzers basiert. Die Grundidee ist, dass ich Benutzer A an Punkt A und Benutzer B an einem anderen Punkt B habe. Beide Benutzer haben Suchfilter, die bestimmen, wie weit ein Benutzer sein kann, um eine Übereinstimmung zu erzielen. Diese Entfernung ist in Kilometer. A crude depictionGeospatial-Abfrage erstellen, um zwei Benutzer innerhalb des jeweils anderen Radius zu finden

Anyways wäre es möglich, dies in einer einzigen Vanilla-Abfrage zu tun (ohne eine Aggregat-Abfrage verwenden)? Hier ist die Frage, die ich bis jetzt habe

var loc = userA.location; 
var rad = userA.radius; 

{$near : { 
     $geometry : { 
      type : "Point", 
      coordinates : loc 
     }, 
     $maxDistance : rad 
    } 
} 

Wie berücksichtige ich die B-Präferenz des Benutzers obwohl?

Ich plante, eine Geometrie zu speichern, die im Grunde ihren Präferenzkreis war, und dann zu sehen, ob sich UserA in diesem Kreis befand, aber das scheint einfach nicht richtig zu sein.

Antwort

2

Sie haben bereits die radius Eigenschaft auf jedem Benutzer gespeichert, so dass eine gute Sache ist, und nicht nur für eine $maxDistance Option, sondern auch als prüft, ob der Abstand zwischen den Benutzern ist „kleiner als“ die radius Attribut.

Was Sie jetzt im Grunde brauchen, ist eine Möglichkeit, diese Distanz zu "sehen" und zu "vergleichen". Dazu verwenden Sie die Zusammenfassung Rahmen und $geoNear:

db.users.aggregate([ 
    { "$geoNear": { 
     "near": { 
      "type": "Point", 
      "coordinates": userA.location 
     }, 
     "spherical": true, 
     "maxDistance": userA.radius, 
     "distanceField": "distance" 
    }}, 
    { "$redact": { 
     "$cond": { 
      "if": { "$lt": [ "$distance", "$radius" ] }, 
      "then": "$$KEEP", 
      "else": "$$PRUNE" 
     } 
    }} 
]) 

Also, was macht es die gleiche Art von $near Ergebnis zusammen mit dem "maxDistance" Zwang, aber eigentlich gibt eine zusätzliche Eigenschaft in den genannten "distanceField", die die tatsächliche Entfernung führt zwischen gefunden "Benutzer". Die Option "spherical" ist erforderlich, wenn der Index "2dsphere" lautet.

Als eine Aggregation "Pipeline" ermöglicht dies eine andere Operation auf die Ausgabe wirken. Die Stufe $redact führt einen "logischen Vergleich" der vorhandenen Daten "radius" und des generierten Feldes "distance" durch, um festzustellen, ob diese Entfernung "kleiner als" die gespeicherten Radiusdaten ist. Nur

, wenn dieser Zustand ist true ist das Dokument über $$KEEP zurückgegeben, ansonsten den Abstand größer ist, als der Benutzer Radius wie das Dokument aus Ergebnissen über $$PRUNE entfernt wird.

So erstellen Sie einen Vergleich, der die radius Benutzerdaten für die Rückgabe der Ergebnisse berücksichtigt.

+0

Neil vielen Dank, das ist eine fantastische Antwort. Eine letzte Frage, wenn es Ihnen nichts ausmacht, habe ich das Radius-Feld in Metern, und wenn ich diese Abfrage ausführen, ist das $ distance-Feld eine wirklich kleine Zahl, wissen Sie zufällig, in welchen Einheiten sie sich befinden? Die [Docs] (https://docs.mongodb.org/manual/reference/operator/aggregation/geoNear/) scheinen das nicht zu erwähnen. Sind sie im Radiant? –

+0

@naughtyboy Wie sind die tatsächlichen Koordinaten gespeichert? Wenn sie im GeoJSON-Format vorliegen, ist die zurückgegebene "Entfernung" tatsächlich in Metern. Aber wenn nicht, dann müssen Sie wahrscheinlich von Radianten konvertieren, und das gleiche gilt auch für die "maxDistance". Sie können die mathematischen Ausdrücke hinzufügen, aber es ist wahrscheinlich viel einfacher und sinnvoll, die Daten stattdessen in GeoJSON zu konvertieren. –

+0

Hmm, ich würde auf jeden Fall lieber mit Zählern umgehen. Die Daten werden in GeoJSON als solche gespeichert. Loc: {type: "Point", Koordinaten: [-80.5863052, 22.7906625]}, radius: 500'. Die Koordinaten sind im 'long, lat'-Format, der Radius ist in Metern und ich habe auch einen Index für das Feld erstellt:' {loc: '2dsphere'} '. Sind Sie sich nicht sicher, ob mir etwas fehlt? –

Verwandte Themen