mongodb 循环管道 geoNear

问题描述

我遇到了一个问题,我试图在查找中获取当前文档附近的一些文档。如果我手动输入 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}
]

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...