【问题标题】:$geowithin with Foriegn Collection on $lookup$geowithin 与 $lookup 上的 Foriegn 集合
【发布时间】:2018-03-02 15:58:12
【问题描述】:

我有两个集合 Members 和 MobileUserLocations - 每个用户的位置都保存(可以是多个)作为外部字段的 userId。

成员:

{
  _id: ObjectId("591553ffa4233a181506880c"),
  userName: "Test user"
}

MobileUserLocations:

{ _id: ObjectId("59156070a4233a1815068b6b"),
  userId: ObjectId("591553ffa4233a181506880c"),
  location: {type: "Point", coordinates: [76.9121, 10.2232]]},
  updatedOn: 2017-05-12T07:12:48.626Z,
  status: 1 
},
{ _id: ObjectId("59156070a4233a1815068b6b"),
  userId: ObjectId("591553ffa4233a181506880c"),
  location: {type: "Point", coordinates: [76.8121, 10.1232]]},
  updatedOn: 2017-05-12T07:12:48.626Z,
  status: 1 
}

我想获取半径范围内的成员 - 例如参考特定地理点 5 公里 - 例如:[10.0132295, 76.3630502](lat,lng 格式)。

我试过了:

collection.aggregate([
                                {$match: {_id: { $ne: options.accessToken.userId }},
                                { "$lookup": {
                                    "localField": "_id",
                                    "from": "MobileUserLocations",
                                    "foreignField": "userId",
                                    "as": "userLocInfo"
                                  }
                                },
                                {
                                    $project: {
                                        _id: 1,
                                        userLocInfo: {
                                           "$filter": {
                                                "input": "$userLocInfo",
                                                "as": "userLoc",
                                                "cond": { 
                                                            "$eq": [ "$$userLoc.status", -1],  
                                                       "$$userLoc.location": {"$geoWithin": {"$centerSphere": [[76.3630502, 10.0132295], 5 / 3963.2]}}
                                                        }
                                            } 
                                        }
                                    }
                                },
                                {$unwind: "$userLocInfo"}

                      ]

但没有得到。如果我从过滤条件中删除 $geowithin,它会得到,否则不会得到。但如果我是单独查询集合,我会得到结果。

谁能知道这个问题?

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    这不起作用,因为$geoWithin 不是“逻辑运算符”,而是“查询运算符”,并且只能在使用$match 的聚合管道中使用。对您来说幸运的是,这确实是您想要的。虽然你还不明白为什么:

    collection.aggregate([
      { "$match": { 
        "_id": { "$ne": options.accessToken.userId }
      }},
      { "$lookup": {
        "localField": "_id",
        "from": "MobileUserLocations",
        "foreignField": "userId",
        "as": "userLocInfo"
      }},
      { "$unwind": "$userLocInfo" },
      { "$match": {
        "userLocInfo.status": -1, 
        "userLocInfo.updatedOn": "2017-05-12T12:11:04.183Z", 
        "userLocInfo.location": {
          "$geoWithin": {
            "$centerSphere": [[76.3630502, 10.0132295], 5 / 3963.2]
          }
        }
      }}
    ])
    

    除了它是唯一的工作方式之外,还有一个非常好的理由。要了解,请查看"explain" 输出:

        {
            "$lookup" : {
                "from" : "MobileUserLocations",
                "as" : "userLocInfo",
                "localField" : "_id",
                "foreignField" : "userId",
                "unwinding" : {
                    "preserveNullAndEmptyArrays" : false
                },
                "matching" : {
                    "$and" : [ 
                        {
                            "status" : {
                                "$eq" : -1.0
                            }
                        }, 
                        {
                            "updatedOn" : {
                                "$eq" : "2017-05-12T12:11:04.183Z"
                            }
                        }, 
                        {
                            "location" : {
                                "$geoWithin" : {
                                    "$centerSphere" : [ 
                                        [ 
                                            76.3630502, 
                                            10.0132295
                                        ], 
                                        0.00126160678239806
                                    ]
                                }
                            }
                        }
                    ]
                }
            }
        }
    

    这表明$unwind 和关注$match 都被$lookup 舞台本身所吸引。这意味着$geoWithin和其他条件实际上是在外部集合上执行“之前”返回结果。

    这就是$lookup 处理可能超过 16MB 限制的结果连接的方式。这也是目前“过滤”连接结果的最有效方式。

    所以这才是你真正想要在这里做的。


    根据您问题中的数据,此声明:

    db.members.aggregate([
      { "$lookup": {
        "localField": "_id",
        "from": "MobileUserLocations",
        "foreignField": "userId",
        "as": "userLocInfo"
      }},
      { "$unwind": "$userLocInfo" },
      { "$match": {
        "userLocInfo.location": {
          "$geoWithin": {
            "$centerSphere": [[76.9121, 10.2232], 5 / 3963.2]
          }
        }
      }}
    ])
    

    过滤掉$lookup 中与约束匹配的一个位置:

    /* 1 */
    {
        "_id" : ObjectId("591553ffa4233a181506880c"),
        "userName" : "Test user",
        "userLocInfo" : {
            "_id" : ObjectId("59c3c37359f55d64d6e30297"),
            "userId" : ObjectId("591553ffa4233a181506880c"),
            "location" : {
                "type" : "Point",
                "coordinates" : [ 
                    76.9121, 
                    10.2232
                ]
            },
            "updatedOn" : ISODate("2017-05-12T07:12:48.626Z"),
            "status" : 1.0
        }
    }
    

    【讨论】:

    • 感谢大佬的回复。但我收到以下错误:“$lookup 的参数必须是字符串,展开:{ preserveNullAndEmptyArrays: false } 是类型对象”。
    • @SanjayKumarNS 您误解了答案的上下文。您执行的管道是答案中的 first 代码块。 “第二个”区域是“解释输出”,展示了“MongoDB 解析管道”在发布到服务器时的方式。您实际上并没有使用第二个块。
    • 是的,我也尝试过第一个。但它没有得到记录。
    • @SanjayKumarNS 然后删除一些条件,并实际检查是否存在确实满足$geoWithin 约束或语句中的任何其他条件的数据。你告诉我的“错误”表明你试图直接输入解释输出的内容。您不能直接使用unwindingmatching 参数。您将这些指定为$unwind$match,在$lookup 之后,服务器会对其进行翻译。
    • 我已经给出了匹配的参数,并且我得到了没有 geowithin 条件的输出。并且还有这些位置的文档以获取地理范围
    猜你喜欢
    • 2021-07-24
    • 2017-05-21
    • 2021-09-17
    • 2019-03-11
    • 2021-02-22
    • 2013-09-08
    • 1970-01-01
    相关资源
    最近更新 更多