【问题标题】:$geoNear for a list embeded locations and return distance for all location in list$geoNear 用于列表嵌入位置和列表中所有位置的返回距离
【发布时间】:2020-05-22 15:40:59
【问题描述】:

我有一个user 收藏:


{
    "name": "David",
    "age": 20,
    "addresses": [
        {
            "radius": 10000,
            "location": {
                "type": "Point",
                "coordinates": [106.785299, 20.999999]
            }
        },
        {
            "radius": 30000,
            "location": {
                "type": "Point",
                "coordinates": [105.785299, 20.979733]
            }
        }
    ]
}

每个用户都有一个或多个地址。我想用一个点计算这些地址之间的距离,然后使用计算出的距离与每个地址的半径进行比较。如果距离 addresses 列表中删除地址。我正在使用以下查询:


db.collection.aggregrate(
    {
        "$geoNear": {
            "near": {"type": "Point", "coordinates": [ 105.823620, 21.006047 ]},
            "distanceField": "distance",
            "key": "addresses.location"
        }
    }
)

但是这个查询只返回最近地址的距离,像这样:


{
    "name": "David",
    "age": 20,
    "addresses": [
        {
            "radius": 10000,
            "location": {
                "type": "Point",
                "coordinates": [105.785299, 20.979733]
            }
        },
        {
            "radius": 30000,
            "location": {
                "type": "Point",
                "coordinates": [105.785299, 20.979733]
            }
        }
    ],
    "distance": 110000 // <--- distance is added here, just for nearest addrest
}

我的预期结果:


{
    "name": "David",
    "age": 20,
    "addresses": [
        {
            "radius": 10000,
            "location": {
                "type": "Point",
                "coordinates": [105.785299, 20.979733]
            },
            "distance": 2000``// <------ add distance here for each addesss`
        },
        {
            "radius": 30000,
            "location": {
                "type": "Point",
                "coordinates": [105.785299, 20.979733]
            },
            "distance": 30000 // <------ add distance here for each addesss
        }
    ]
}

所以下一阶段我可以比较 distanceradius 并保持正确的地址 有人知道怎么做吗?谢谢

【问题讨论】:

  • 两个地址的坐标相同,所以它们的距离是相同的。您需要存储 1 个地址 1 个文档,然后$geoNear 可以正确计算您的期望值。然后,您可以将它们分组到所需的输出中
  • @Valijon,抱歉,这只是一个示例数据。当然,所有地址都会有不同的坐标。我已经解决了我的问题

标签: mongodb aggregation-framework


【解决方案1】:

您需要将每个地址存储在单独的文档中:

{
    "_id" : ObjectId("5ec77d127df107cd889d567d"),
    "name" : "David",
    "age" : 20,
    "addresses" : {
        "radius" : 10000,
        "location" : {
            "type" : "Point",
            "coordinates" : [ 
                105.785299, 
                20.979733
            ]
        }
    }
},
{
    "_id" : ObjectId("5ec77f7843732e8f9a63bf67"),
    "name" : "David",
    "age" : 20,
    "addresses" : {
        "radius" : 30000,
        "location" : {
            "type" : "Point",
            "coordinates" : [ 
                105.795299, 
                20.989733
            ]
        }
    }
}

现在,我们执行$geoNear$group 阶段:

db.user.aggregate([
  {
    "$geoNear": {
      "near": {
        "type": "Point",
        "coordinates": [
          105.823620,
          21.006047
        ]
      },
      "distanceField": "distance",
      "key": "addresses.location"
    }
  },
  {
    "$group": {
      "_id": "$name",
      "name": {
        "$first": "$name"
      },
      "age": {
        "$first": "$age"
      },
      "addresses": {
        "$push": {
          "$mergeObjects": [
            "$addresses",
            {
              "distance": "$distance"
            }
          ]
        }
      }
    }
  }
])

【讨论】:

  • 如果将地址存储在单个文档中,可能会产生冗余数据。但是我们必须这样做,然后我们才能做到$geoNear,对吗?
  • @PhùngXuânAnh 是的。我们需要单独存储它。此外,您可以将坐标单独存储在 collection1 中,并将用户数据存储在 collection2 中。然后,我们可以表演$lookup舞台加入他们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-22
  • 2017-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多