Partager via


$near

L’opérateur $near retourne les documents dont le champ d’emplacement est proche d’un point spécifié, triés par distance. Il nécessite un index « 2dsphere » et retourne les documents du plus proche au plus éloigné.

Syntaxe

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

Paramètres

Paramètre Descriptif
location field Le champ qui contient le point GeoJSON
$geometry Objet GeoJSON Point qui indique le point central
$maxDistance Optional. Distance maximale en mètres à partir du point central
$minDistance Optional. Distance minimale en mètres à partir du point central

Prérequis

Pour de meilleures performances, commencez par créer l’index requis 2dsphere .

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

Examples

Comprenons l’utilisation avec un exemple json à partir du jeu de données stores.

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

La requête récupère les deux magasins les plus proches à un point géographique spécifique (70.1272, 69.7296) à l’aide de la recherche géospatiale. Cette requête recherche les emplacements les plus proches du point donné et retourne les magasins dans l’ordre croissant de distance du point.

db.stores.find({
  'location': {
    $near: {
      $geometry: {
        type: "Point",
        coordinates: [69.7296, 70.1272]  // [longitude, latitude]
      }
    }
  }
}, {
  name: 1,
  location: 1
}).limit(2)

Les deux premiers résultats retournés par cette requête sont les suivants :

[
  {
     "_id": "3882eb86-5dd6-4701-9640-f670ccb67859",
     "name": "Fourth Coffee | DJ Equipment Stop - Schuppestad",
     "location": { "lat": 69.4923, "lon": 70.1851 }
   },
   {
     "_id": "bbec6d3e-1666-45b4-8803-8b7ef8544845",
     "name": "First Up Consultants | Baby Products Bargains - South Keenan",
     "location": { "lat": 69.2158, "lon": 70.3328 }
   }
]

Exemple 2 : Utilisation de la distance minimale et maximale

La requête récupère les magasins dans un intervalle de 20 km à 200 km à partir d’un point spécifié et calcule leurs distances en kilomètres. Cette requête recherche dans une zone « en forme de donut » : recherche des magasins à au moins 20 mètres, mais pas plus de 200 mètres à partir du point spécifié.

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