$nearSphere

$nearSphere 연산자는 구면 기하 도형을 사용하여 거리를 계산하여 구면 위의 지정된 지점 근처에 위치 필드가 있는 문서를 반환합니다. 연산자가 $near보다 지구 기반 계산에 더 정확합니다.

문법

{
  <location field>: {
    $nearSphere: {
      $geometry: {
        type: "Point",
        coordinates: [<longitude>, <latitude>]
      },
      $maxDistance: <distance in meters>,
      $minDistance: <distance in meters>
    }
  }
}

매개 변수

매개 변수 Description
location field GeoJSON Point를 포함하는 필드
$geometry 중심점을 지정하는 GeoJSON Point 개체
$maxDistance Optional. 구면 표면에서의 최대 거리(미터)
$minDistance Optional. 구면 표면에서의 최소 거리(미터)

예시

stores 데이터 세트의 샘플 json을 통해 사용법을 이해해 보겠습니다.

{
  "_id": "a715ab0f-4c6e-4e9d-a812-f2fab11ce0b6",
  "name": "Lakeshore Retail | Holiday Supply Hub - Marvinfort",
  "location": { "lat": -74.0427, "lon": 160.8154 },
  "staff": { "employeeCount": { "fullTime": 9, "partTime": 18 } },
  "sales": {
    "salesByCategory": [ { "categoryName": "Stockings", "totalSales": 25731 } ],
    "revenue": 25731
  },
  "promotionEvents": [
    {
      "eventName": "Mega Savings Extravaganza",
      "promotionalDates": {
        "startDate": { "Year": 2023, "Month": 6, "Day": 29 },
        "endDate": { "Year": 2023, "Month": 7, "Day": 7 }
      },
      "discounts": [
        { "categoryName": "Stockings", "discountPercentage": 16 },
        { "categoryName": "Tree Ornaments", "discountPercentage": 8 }
      ]
    },
    {
      "eventName": "Incredible Discount Days",
      "promotionalDates": {
        "startDate": { "Year": 2023, "Month": 9, "Day": 27 },
        "endDate": { "Year": 2023, "Month": 10, "Day": 4 }
      },
      "discounts": [
        { "categoryName": "Stockings", "discountPercentage": 11 },
        { "categoryName": "Holiday Cards", "discountPercentage": 9 }
      ]
    },
    {
      "eventName": "Massive Deal Mania",
      "promotionalDates": {
        "startDate": { "Year": 2023, "Month": 12, "Day": 26 },
        "endDate": { "Year": 2024, "Month": 1, "Day": 2 }
      },
      "discounts": [
        { "categoryName": "Gift Bags", "discountPercentage": 21 },
        { "categoryName": "Bows", "discountPercentage": 19 }
      ]
    },
    {
      "eventName": "Super Saver Soiree",
      "promotionalDates": {
        "startDate": { "Year": 2024, "Month": 3, "Day": 25 },
        "endDate": { "Year": 2024, "Month": 4, "Day": 1 }
      },
      "discounts": [
        { "categoryName": "Tree Ornaments", "discountPercentage": 15 },
        { "categoryName": "Stockings", "discountPercentage": 14 }
      ]
    },
    {
      "eventName": "Fantastic Savings Fiesta",
      "promotionalDates": {
        "startDate": { "Year": 2024, "Month": 6, "Day": 23 },
        "endDate": { "Year": 2024, "Month": 6, "Day": 30 }
      },
      "discounts": [
        { "categoryName": "Stockings", "discountPercentage": 24 },
        { "categoryName": "Gift Wrap", "discountPercentage": 16 }
      ]
    },
    {
      "eventName": "Price Plunge Party",
      "promotionalDates": {
        "startDate": { "Year": 2024, "Month": 9, "Day": 21 },
        "endDate": { "Year": 2024, "Month": 9, "Day": 28 }
      },
      "discounts": [
        { "categoryName": "Holiday Tableware", "discountPercentage": 13 },
        { "categoryName": "Holiday Cards", "discountPercentage": 11 }
      ]
    }
  ],
  "company": "Lakeshore Retail",
  "city": "Marvinfort",
  "storeOpeningDate": { "$date": "2024-10-01T18:24:02.586Z" },
  "lastUpdated": { "$timestamp": { "t": 1730485442, "i": 1 } },
  "storeFeatures": 38
}

성능을 향상시키려면 필요한 2dsphere 인덱스 만들기부터 시작합니다.

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

쿼리는 구형(지구와 유사한) 표면에서 지정된 지점(-141.9922, 16.8331)에 가장 가까운 저장소를 검색합니다.

db.stores.find({
  'location': {
    $nearSphere: {
      $geometry: {
        type: "Point",
        coordinates: [-141.9922, 16.8331]
      }
    }
  }
}, {
  name: 1,
  location: 1
}).limit(2)

이 쿼리에서 반환된 처음 두 가지 결과는 다음과 같습니다.

[
  {
    "_id": "643b2756-c22d-4063-9777-0945b9926346",
    "name": "Contoso, Ltd. | Outdoor Furniture Corner - Pagacfort",
    "location": {
      "type": "Point",
      "coordinates": [152.1353, -89.8688]
    }
  },
  {
    "_id": "daa71e60-75d4-4e03-8b45-9df59af0811f",
    "name": "First Up Consultants | Handbag Corner - South Salvatore",
    "location": {
      "type": "Point",
      "coordinates": [150.2305, -89.8431]
    }
  }
]

예제 2: 복합 거리 분석

이 쿼리는 지점(65.3765, -44.8674)에서 20미터에서 200미터 사이의 저장소를 검색합니다. 쿼리는 "도넛 모양" 영역을 검색하여 지정된 지점에서 200미터 이상 떨어져 있지만 200미터 이하인 상점을 찾습니다.

db.stores.aggregate([
  {
    $geoNear: {
      near: {
        type: "Point",
        coordinates: [65.3765, -44.8674]
      },
      distanceField: "sphericalDistance",
      minDistance: 20,
      maxDistance: 200,
      spherical: true
    }
  },
  {
    $project: {
      name: 1,
      location: 1,
      distanceKm: { $divide: ["$sphericalDistance", 1000] },
      _id: 0
    }
  },
  {
    $limit: 2
  }
])

주요 차이점은 연산자 $nearSphere$near입니다.

  • 이전 방법은 거리 계산에 구체 기하학을 사용합니다.
  • 지구 기반 거리 계산에는 앞서 언급한 것이 더 정확합니다.
  • 전자는 정확한 글로벌 거리 계산이 필요한 애플리케이션에 더 적합합니다.