问题描述
我遇到了一个问题,我试图在查找中获取当前文档附近的一些文档。如果我手动输入 lon/lat,以下查询将起作用,但尝试使用“let”中的任何内容都会失败。如何在查找管道中的 geoNear 中引用父文档的位置?
[
{
"$match":{
'assessed_improvement_value':{'$gt':500},'sqft':{'$gt':500}
}
},{
"$lookup":{
"from":"properties","let":{
'lon':{"$arrayElemAt":["$location.coordinates",0]},'lat':{"$arrayElemAt":["$location.coordinates",1]},},'pipeline': [
{
"$geoNear": {
"near": { "type": "Point","coordinates": [ "$$lon","$$lat" ] },"distanceField": "distance","spherical": true
}
},{"$limit":10}
],"as":"comps",}
},{"$limit":10}
]
解决方法
更新 我发布的第一种方法实际上是一团糟。我现在想出了一个更清洁的解决方案。我希望这对未来的人有所帮助
[
{
"$lookup":{
"from":"properties","let":{
'plon':{"$arrayElemAt":["$location.coordinates",0]},'plat':{"$arrayElemAt":["$location.coordinates",1]},},'pipeline': [
{
"$addFields":{
"distance":{
"$function":{
"body":"""
function(plonRad,platRad,lonRad,latRad) {
var R = 6373.0;
var dlon = lonRad - plonRad;
var dlat = latRad - platRad;
if((dlon == 0) || (dlat == 0)) {
return 0;
}
var a = Math.pow(Math.sin(dlat / 2),2)+ Math.cos(platRad) * Math.cos(latRad) * Math.pow(Math.sin(dlon / 2),2);
var c = 2 * Math.atan2(Math.sqrt(a),Math.sqrt(1 - a));
var dist = R * c;
return dist*0.621371;
}
""","args":[
{"$toDouble":{"$degreesToRadians":"$$plon"}},{"$toDouble":{"$degreesToRadians":"$$plat"}},{"$toDouble":{"$degreesToRadians":{"$arrayElemAt":["$location.coordinates",0]}}},1]}}}],"lang":"js"
}
}
}
},{
"$match":{
"distance":{"$gt":0}
}
},{"$sort":{"distance":1}},{"$limit":20}
],"as":"comps",}
}
]
我猜这是一个老错误,无论出于何种原因从未修复。这感觉像一团糟,但它是一个有效的解决方案。这会手动计算以英里为单位的距离。
[
{
"$match":{
'assessed_improvement_value':{'$gt':500},'sqft':{'$gt':500}
}
},{
"$lookup":{
"from":"properties","let":{
'lon':{"$arrayElemAt":["$location.coordinates",'lat':{"$arrayElemAt":["$location.coordinates",'pipeline': [
{
"$addFields": {
'plonRad':{"$degreesToRadians":"$$lon"},'platRad':{"$degreesToRadians":"$$lat"},'lonRad':{"$degreesToRadians":{"$arrayElemAt":["$location.coordinates",0]}},'latRad':{"$degreesToRadians":{"$arrayElemAt":["$location.coordinates",1]}},}
},{
'$addFields':{
"dlon":{
"$subtract":["$plonRad","$lonRad"]
},"dlat":{
"$subtract":["$platRad","$latRad"]
},{
"$addFields":{
'a':{
"$multiply":[
{
"$add":[
{
"$pow":[
{
"$sin":{
"$divide":["$dlat",2]
}
},2
]
},{
"$cos":"$platRad"
}
]
},{
"$add":[
{
"$pow":[
{
"$sin":{
"$divide":["$dlon",{
"$cos":"$latRad"
}
]
}
]
},{
"$addFields":{
"c":{
"$atan2":[
{"$sqrt":"$a"},{"$sqrt":{"$subtract":[1,"$a"]}}
]
}
}
},{
"$addFields":{
"distance":{
"$divide":[
{"$multiply":[6373.0,"$c"]},1609.34
]
}
}
},{"$limit":10}
],}
},{"$limit":10}
]