甚至比原来更优化,您现在可以在初始 $geoNear 之后的 $match 阶段内使用 $expr:
db.collection.aggregate([
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [ 23.027573, 72.50675800000001 ],
},
"distanceField": "distance"
}},
{ "$match": { "$expr": { "$lte": [ "$distance", "$radius" ] } }}
])
实际上比第一次编写时更优化。现在我们可以只使用 $redact 而不是 $project 布尔值和稍后的 $match:
db.collection.aggregate([
// Match documents "near" the queried point
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [ 23.027573, 72.50675800000001 ],
},
"distanceField": "distance"
}},
// Calculate if distance is within radius and remove if not
{ "$redact": {
"$cond": {
"if": { "$lte": [ "$distance", "$radius" ] },
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
您已按照应有的方式准确存储信息,但获取结果的方法与您想象的不同。
您要使用的是$geoNear,特别是该运算符的aggregation framework 形式。这是你要做的:
db.collection.aggregate([
// Match documents "near" the queried point
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [ 23.027573, 72.50675800000001 ],
},
"distanceField": "distance"
}},
// Calculate if distance is within radius
{ "$project": {
"location": 1,
"radius": 1,
"distance": 1,
"within": { "$lte": [ "$distance", "$radius" ] }
}},
// Match only documents within the radius
{ "$match": { "within": true } }
])
因此,该表单允许在结果中“投影”到查询点的距离,而查询也只会返回最近的文档。
然后您使用逻辑比较来查看“距离”值是否小于“半径”,因此在圆内。
最后,您匹配以仅过滤掉那些“内部”断言为真的结果。
您可以向$geoNear 添加其他选项,如文档中所示。我还强烈建议您的存储也应使用 GeoJSON 格式,因为这可能与您可能用于处理获得的结果的任何其他库更兼容。