次の方法で共有


$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 Object 距離を計算するポイント
distanceField 計算距離を含むフィールド
maxDistance Number Optional. ポイントからの最大距離 (メートル単位)
minDistance Number Optional. ポイントからの最小距離 (メートル単位)
query ドキュメント オプションのクエリ条件
includeLocs ブール値 Optional. 結果に場所を含める
distanceMultiplier Number Optional. 距離にこの値を乗算する
spherical ブール値 2dsphere インデックスの場合は true にする必要があります
key Optional. 距離の計算に使用するフィールド パス

例示

stores コレクションのこのサンプル ドキュメントについて考えてみましょう。

{
  "_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
    }
  }
])

このクエリによって返される最初の 3 つの結果は次のとおりです。

[
    {
        "_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: 距離制限とオプションのクエリを使用する

このクエリでは、10 人以上のフルタイム スタッフがいる "Proseware Home Entertainment Hub" から 30 KM 以内のすべてのストアを取得します。

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
    }
  }
])

このクエリによって返される最初の 3 つの結果は次のとおりです。

[
    {
        "_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
    }
]

制限事項

  • シャード コレクションでは使用できません
  • パイプラインごとに 1 つの$geoNear ステージのみ
  • パイプラインの最初のステージである必要があります