$geoNear(聚合)

适用对象: MongoDB vCore

$geoNear聚合阶段计算指定点与每个文档中的位置字段之间的距离,按距离对文档进行排序,并且可以选择按距离限制结果。

语法

运算符的 $isArray 语法如下所示:

{
  $geoNear: {
    near: {
      type: "Point",
      coordinates: [<longitude>, <latitude>]
    },
    distanceField: <field to store distance>,
    maxDistance: <optional maximum distance in meters>,
    minDistance: <optional minimum distance in meters>,
    query: <optional query conditions>,
    includeLocs: <optional boolean to include locations>,
    distanceMultiplier: <optional distance multiplier>,
    spherical: <boolean, must be true>,
    key: <optional field path>
  }
}

参数

参数 类型 DESCRIPTION
near 物体 计算距离的点
distanceField 字符串 包含计算距离的字段
maxDistance 编号 可选。 距离点的最大距离(以米为单位)
minDistance 编号 可选。 距离点的最小距离(以米为单位)
query 文档 可选查询条件
includeLocs 布尔 可选。 在结果中包含位置
distanceMultiplier 编号 可选。 将距离乘以此值
spherical 布尔 对于 2dsphere 索引,必须为 true
key 字符串 可选。 用于计算距离的字段路径

例子

示例 1:基本距离计算

查找“VanArsdel 图片框商店”位置附近的所有商店,按距离排序:

db.stores.aggregate([
  {
    $geoNear: {
      near: {
        type: "Point",
        coordinates: [-141.9922, 16.8331]  // VanArsdel Picture Frame Store location
      },
      distanceField: "distance",
      spherical: true
    }
  },
  {
    $project: {
      name: 1,
      distance: 1
    }
  }
])

这会生成以下输出:

{
    _id: '643b2756-c22d-4063-9777-0945b9926346',
    name: 'Contoso, Ltd. | Outdoor Furniture Corner - Pagacfort',
    distance: 5458613.2813355485
  },
  {
    _id: 'daa71e60-75d4-4e03-8b45-9df59af0811f',
    name: 'First Up Consultants | Handbag Corner - South Salvatore',
    distance: 5469362.958855379
  },
  {
    _id: '02a78a15-b1fc-4bbd-ae1d-641b7428dc78',
    name: 'VanArsdel, Ltd. | Kitchen Appliance Corner - Llewellynberg',
    distance: 5472684.4628977
  }..

示例 2:具有距离限制和可选查询

查找距离“Proseware 家庭娱乐中心”30 公里范围内、全职员工超过 10 人的商店:

db.stores.aggregate([
  {
    $geoNear: {
      near: {
        type: "Point",
        coordinates: [69.7296, 70.1272]  // "Proseware Home Entertainment Hub" location
      },
      distanceField: "distance",
      maxDistance: 30000,  // 30 kilometers in meters
      query: { "staff.totalStaff.fullTime": { $gt: 10 } },
      spherical: true
    }
  },
  {
    $project: {
      name: 1,
      distance: 1,
      "staff.totalStaff.fullTime": 1
    }
  }
])

这会生成以下输出:

  {
    _id: 'bbec6d3e-1666-45b4-8803-8b7ef8544845',
    name: 'First Up Consultants | Baby Products Bargains - South Keenan',
    staff: { totalStaff: { fullTime: 19 } },
    distance: 29934.71888123174
  }

示例 3:包括位置数据和距离乘数

查找距离为公里的附近商店,并包括位置数据:

db.stores.aggregate([
  {
    $geoNear: {
      near: {
        type: "Point",
        coordinates: [-38.4071, -47.2548]  // "Fabrikam Car Accessory Outlet" location
      },
      distanceField: "distanceInKm",
      includeLocs: "storeLocation",
      distanceMultiplier: 0.001,  // Convert meters to kilometers
      spherical: true
    }
  },
  {
    $project: {
      name: 1,
      distanceInKm: 1,
      storeLocation: 1
    }
  }
])

这会生成以下输出:

  {
    _id: 'b677846e-bb73-46ec-9cba-7d94afee382c',
    name: 'Northwind Traders | Health Food Shoppe - Brooklynmouth',
    storeLocation: { lat: -38.3032, lon: -132.7866 },
    distanceInKm: 9.095634270192285
  },
  {
    _id: '27c64b44-2382-4477-b3ce-c08e74882156',
    name: 'Relecloud | VR Headset Gallery - West Jonasbury',
    storeLocation: { lat: -37.9628, lon: -132.6637 },
    distanceInKm: 34.7104536140246
  },
  {
    _id: '505e83eb-09bc-46a4-ba85-16135611b9de',
    name: 'Fabrikam, Inc. | Pharmacy Hub - Elijahville',
    storeLocation: { lat: -38.0349, lon: -47.9571 },
    distanceInKm: 82.92766541748313
  }

局限性

  • 不能与分片集合一起使用
  • 每个管道只有一个 $geoNear 阶段
  • 必须是管道中的第一个阶段