共用方式為


$geoNear

$geoNear 彙總階段會計算每個文件中指定點與位置欄位之間的距離、依距離排序文件,以及選擇性地依距離限制結果。

語法

{
  $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 Number 選擇性。 距離該點的最遠距離 (以公尺為單位)
minDistance Number 選擇性。 距離該點的最短距離 (以公尺為單位)
query 文件 選擇性查詢條件
includeLocs 布林值 選擇性。 在結果中包含位置
distanceMultiplier Number 選擇性。 將距離乘以此值
spherical 布林值 2dsphere 索引必須為 true
key 繩子 選擇性。 用於計算距離的欄位路徑

範例

請參考商店集合中的此範例檔。

{
  "_id": "2cf3f885-9962-4b67-a172-aa9039e9ae2f",
  "name": "First Up Consultants | Bed and Bath Center - South Amir",
  "location": {
    "lat": 60.7954,
    "lon": -142.0012
  },
  "staff": {
    "totalStaff": {
      "fullTime": 18,
      "partTime": 17
    }
  },
  "sales": {
    "totalSales": 37701,
    "salesByCategory": [
      {
        "categoryName": "Mattress Toppers",
        "totalSales": 37701
      }
    ]
  },
  "promotionEvents": [
    {
      "eventName": "Price Drop Palooza",
      "promotionalDates": {
        "startDate": {
          "Year": 2024,
          "Month": 9,
          "Day": 21
        },
        "endDate": {
          "Year": 2024,
          "Month": 9,
          "Day": 30
        }
      },
      "discounts": [
        {
          "categoryName": "Bath Accessories",
          "discountPercentage": 18
        },
        {
          "categoryName": "Pillow Top Mattresses",
          "discountPercentage": 17
        }
      ]
    }
  ]
}

範例 1:基本距離計算

此查詢會擷取「VanArsdel Picture Frame Store」位置附近的所有商店,並依距離排序:

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 Home Entertainment Hub」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 階段
  • 必須是管線中的第一個階段