Reputation: 2149
I am creating a matching system based on user proximity. The basic idea is I have user A at point A and user B at another point B. Both users have search filters that determine how far a user can be to make a match. This distance is in Kilometers.
Anyways would it be possible to do this in a single vanilla query (without using an aggregate query)? Here is the query I have so far
var loc = userA.location;
var rad = userA.radius;
{$near : {
$geometry : {
type : "Point",
coordinates : loc
},
$maxDistance : rad
}
}
How do I account for user's B preference though?
I was planning to store a geometry that was basically their circle of preference and then see if userA was within that circle, but this just doesn't seem right.
Upvotes: 2
Views: 352
Reputation: 151112
You already have the radius
property stored on each user, so that is a good thing, and not only for a $maxDistance
option, but also as a check to see if the distance between users is "less than" the radius
attribute.
What you now basically need is a way to "see" that distance and "compare". For this you use the aggregation framework and $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"
}
}}
])
So what this does it executes the same sort of $near
result along with the "maxDistance"
constraint, but actually returns an additional property in the named "distanceField"
representing the actual distance between found 'users'. The "spherical"
option is required when the index is "2dsphere"
.
As an aggregation "pipeline", this allows another operation to act on the output. The $redact
stage makes a "logical comparison" of the existing "radius"
data and the generated "distance"
field, to see if that distance is "less than" the stored radius data.
Only when that condition is true
is the document returned via $$KEEP
, otherwise the distance is larger than the users radius as the document is removed from results via $$PRUNE
.
That's how you make a comparison that respects the radius
on the user data for returning results.
Upvotes: 3