MongoDB $ geoNear降低距离返回值的准确性

时间:2019-07-19 01:55:53

标签: javascript node.js mongodb geonear

我正在对MongoDB中的用户模型执行查询,并希望首先按其距离(以$geoNear为单位,以公里为单位),然后按其上次登录时间对搜索结果进行排序。问题是,distance属性在浮点变量中以米的形式返回,该变量太精确了。

这意味着我的结果按以下顺序排序:

+----------------+------------------------+
|    distance    |  lastLoggedInTime      |
+----------------+------------------------+
|    1700        |  16 hours ago          |
|    1700.1      |  4 hours ago           |
|    2220        |  3 months ago          |
|    2220.5      |  1 day ago             |
+----------------+------------------------+

这些值相同,其中km = Math.ceil(distance / 1000)的排序如下:

+----------------+------------------------+
|    km          |  lastLoggedInTime      |
+----------------+------------------------+
|    2           |  4 hours ago           |
|    2           |  16 hours ago          |
|    3           |  1 day ago             |
|    3           |  3 months ago          |
+----------------+------------------------+
这就是我想要的。我使这些值更具可读性,以突出显示我所面临的问题。实际值看起来像这样:

{
    distance: 2234.3715776698273,
    lastLoggedInTime: '2019-07-13T02:14:30.173Z'
}

我尝试自己更改distance属性:

      user.distance = Math.ceil(user.travel.distance / 1000);

但是由于distance是由$geoNear添加到搜索查询本身中的,所以我只能在查询运行后才能访问它。因此,当我可以访问它时,结果已经不合需要地排序了。

还有distanceMultiplier属性,我可以将其附加到查询中,如下所示:

      $geoNear: {
        spherical: true,
        includeLocs: 'loc',
        distanceField: 'distance',
        distanceMultiplier: 0.001,        
        near: {
          type: 'Point',
          coordinates: [lng, lat]
        },
        ...
      }

但是结果仍然以浮点数形式返回((2234.3715776698273变为2.2343715776698273)),它具有相同的问题。我还有其他选择吗?

1 个答案:

答案 0 :(得分:0)

尝试将操作转换为聚合,然后使用$project$sort来按截断的距离字段创建和排序。 $ project阶段将使用$trunc提供简化的距离字段。

例如:

db.coll.aggregate([
  { "$geoNear" : {
    {
        spherical: true,
        includeLocs: 'loc',
        distanceField: 'distance',
        near: {
          type: 'Point',
          coordinates: [lng, lat]
        },
        ...
     }
  },
  {
    "$project": {
      "truncated_distance" : { "trunc" : [ "$distance", 0 ] }
    }
  },
  {
    "$sort" : {
      "truncated_distance" : 1, 
      "lastLoggedInTime": 1
    }
  }
])