通过最近的地理位置和过滤对数据进行排序

时间:2018-05-21 15:29:31

标签: javascript jquery

我正在尝试找到有人正在使用我的应用程序的正确建筑。现在我设法做了一个非常糟糕的过滤,我需要改进它。

我的目标是过滤将最近的建筑物返回给使用该应用程序的人,因此尽可能过滤它,而不会在同一建筑物中移动时产生错误。

我的fetch返回一个如下所示的api JSON数组:

    <!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <style>
        body {
            background-color: black;
            color: white;
        }
    </style>
</head>
<body>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
    <p>hello</p>
</body>
</html>

这是我的代码

{
"data": [
{
  "id": 1,
  "city": "CITY",
  "building_name": "Building 1",
  "building_address": "Address 123",
  "latitude":  "57.7052809",
  "longitude": "16.9367817"
},
{
  "id": 2,
  "city": "CITY",
  "building_name": "Building 2",
  "building_address": "Address 456",
  "latitude":  "35.7054509",
  "longitude": "16.9366141"
}
],
}

4 个答案:

答案 0 :(得分:2)

使用两点之间的“距离”来找到最近的点。您不能保证用户的建设,但您可以保证哪一个最接近用户的坐标。

var keys = Object.entries(data.data).map(([inst, key]) => key);
var returnedBuilding = 
  keys.reduce((prevCord, thing) => {
    var dist = getDistance(userCoordinates.latitude, userCoordinates.longitude, thing.latitude, thing.longitude);
    var prevDist = getDistance(userCoordinates.latitude, userCoordinates.longitude, prevCord.latitude, prevCord.longitude);
    return dist < prevDist? thing : prevCord;
}, keys[0]);

以下是我从this post引用的getDistance函数。但是你可以编写自己的,更简单的,因为你只处理小距离(我假设)。

function getDistance(lat1, lon1, lat2, lon2) 
{
  var R = 6371; // km
  var dLat = toRad(lat2-lat1);
  var dLon = toRad(lon2-lon1);
  var lat1 = toRad(lat1);
  var lat2 = toRad(lat2);

  var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2); 
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
  var d = R * c;
  return d;
}

// Converts numeric degrees to radians
function toRad(Value) 
{
    return Value * Math.PI / 180;
}

答案 1 :(得分:1)

您可以使用haversine公式来确定哪个建筑物最接近。

根据经度和纬度,半球公式确定球体上两点之间的大圆距离。 tl; dr,你可以这样做,找到你自己和建筑物之间的距离,然后准确地确定哪个是最接近的。

这是SO的另一篇关于在javascript中使用它的文章: Using the Haversine Formula in Javascript

答案 2 :(得分:0)

您可以遍历每个建筑物并根据距离

找到最近的建筑物
var closestBuilding = building[0];
var closestDistance = distanceFrom(user, building);
building.forEach(function(building) {
  var distanceFrom = distanceFrom(user, building);
  if(closestDistance > distanceFrom){
    closestBuilding = building;
    closestDistance = distanceFrom;
  } 
})
console.log(closestBuilding);

function distanceFrom(user, building) { /* your distance code */ }

答案 3 :(得分:-1)

我强烈建议您考虑更改数据模型以利用存储在mongoDB数据库中的GeoJSON点。这将允许您利用mongoDB强大的内置geospatial queries。使用上面的现有数据模型作为起点,您的新数据模型可能如下所示:

{
  "id": 1,
  "city": "CITY",
  "building_name": "Building 1",
  "building_address": "Address 123",
  "location": {
    "type": "Point",
    "coordinates": [ // IMPORTANT: note the order is longitude, latitude
      16.9367817, // longitude
      57.7052809, // latitude
    ]
  }
}

上面对象中的location属性是GeoJSON点。现在,您不是从数据库中获取每个位置并在客户端自己进行计算,而是查询建筑物数据库中最近的建筑物到用户的位置。假设用户坐标为latitude: 35.7053509longitude: 16.9362301,您的查询可能看起来像这样(通过GET请求):

http://localhost:8888/api/buildings?lat=35.7053509&lng=16.9362301&maxDistance=2000

mongoDB文档提供了有关如何处理地理空间查询的示例。此示例取自文档,是您的api处理请求的方式:

// If you're using express.js, pull the params off the query object
const { lat, lng, maxDistance } = req.query;
const buildings = db.buildings.find(
  {
    location:
      {
        $near:
          {
            $geometry: { type: "Point", coordinates: [lng, lat] },
            $maxDistance: maxDistance
          }
      }
  }
)
  .then(buildings => res.json({ buildings })) // respond to the client
  .catch(err => console.log(err)) // do something with the error

来自您服务器的响应将是指定maxDistance内所有建筑物的列表,按用户位置(距离最近)的距离排序。 MongoDB地理空间查询非常快速且高效。您甚至可以从db.find操作切片第一个结果,如果您的客户只想要一个结果,则从您的api返回一个建筑物。

希望这有意义并且有所帮助!如果你没有使用过mongoDB和/或geoJSON对象,那么最初可能看起来有点令人生畏,但相信我,这将使你的生活变得更加容易。当您设置数据库和集合时,可能会发生另一个小问题。您需要确保在建筑物集合中添加索引以支持地理空间查询。来自文档:

db.buildings.createIndex( { location: "2dsphere" } )

然后创建您的收藏并将建筑文档添加到其中。

如果您需要任何澄清,请随时跟进。我建议您阅读mongoDB的文档并在线搜索更多示例。