MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Филтриране на документи по разстояние, съхранени в документа с $near

Ако приемем, че вече сте работили върху данните за събитието, докато ги получавате и имате в ръка (ако не сте, това е друг въпрос, но вижте покриващи се курсори ), тогава трябва да имате обект с тези данни, за които да правите запитвания към потребителите.

Следователно това не е случай за оценка на JavaScript с $where , тъй като няма достъп до данните за заявката, върнати от $near операция все пак. Това, което искате вместо това, е $geoNear от рамката за агрегиране. Това може да проектира „разстоянието“, намерено от заявката, и да позволи на по-късен етап да „филтрира“ резултатите спрямо съхранената от потребителя стойност за максималното разстояние, което искат да изминат до публикувани събития:

// Represent retrieved event data
var eventData = {
  eventLocation: {
    latlong: [long,lat]
  }
};

// Find users near that event within their stored distance
User.aggregate(
  [
    { "$geoNear": {
      "near": {
        "type": "Point",
        "coordinates": eventData.eventLocation.latlong
      },
      "distanceField": "eventDistance",
      "limit": 100000,
      "spherical": true
    }},
    { "$redact": {
      "$cond": {
        "if": { "$lt": [ "$eventDistance", "$maxDistance" ] },
        "then": "$$KEEP",
        "else": "$$PRUNE"
      }
    }}
  ]
  function(err,results) {
    // Work with results in here
  }
)

Сега трябва да внимавате с върнатото число, тъй като изглежда, че съхранявате в „наследени координатни двойки“ вместо в GeoJSON, тогава разстоянието, върнато от тази операция, ще бъде в радиани, а не стандартно разстояние. Така че ако приемем, че съхранявате в „мили“ или „километри“ на потребителските обекти, тогава трябва да изчислите чрез формулата, спомената в ръководството под "Изчисляване на разстояния с помощта на сферична геометрия" както е посочено в ръководството.

Основното е, че трябва да разделите на екваториалния радиус на земята, който е 3963,2 мили или 6378,1 километра, за да преобразувате за сравнение с това, което сте съхранили.

Алтернативата е вместо това да се съхранява в GeoJSON, където има последователно измерване в метри.

Ако приемем „километри“, че редът „ако“ става:

"if": { "$lt": [
    "$eventDistance",
    { "$divide": [ "$maxDistance", 6,378.1 ] }
 ]},

За надеждно сравняване на съхранената ви километрична стойност с върнатия резултат в радиани.

Другото нещо, което трябва да знаете е, че $geoNear има "лимит" по подразбиране от 100 резултата, така че трябва да "напомпате" аргумента "лимит" там до броя, за който очакваните потребители евентуално да съвпадат. Може дори да искате да направите това в „списъци с диапазони“ на потребителски идентификатори за наистина голяма система, но можете да стигнете толкова, колкото позволява паметта в рамките на една операция за агрегиране и евентуално да добавите allowDiskUse където е необходимо.

Ако не настроите този параметър, тогава ще бъдат върнати само най-близките 100 резултата (по подразбиране), което може дори да не подхожда на следващата ви операция за филтриране на тези „близо“ до събитието, с което да започнете. Все пак използвайте здрав разум, тъй като със сигурност имате максимално разстояние дори да филтрирате потенциални потребители и това също може да се добави към заявката.

Както беше посочено, целта тук е връщането на разстоянието за сравнение, така че следващият етап е $redact операция, която може да филтрира стойността на собственото „пропътувано разстояние“ на потребителя спрямо върнатото разстояние от събитието. Крайният резултат дава само онези потребители, които попадат в собственото си ограничение на разстоянието от събитието, които отговарят на условията за известяване.

Това е логиката. Проектирате разстоянието от потребителя до събитието и след това сравнявате със съхранената от потребителя стойност за това какво разстояние са готови да изминат. Без JavaScript и всички собствени оператори, които го правят доста бърз.

Освен това, както е отбелязано в опциите и общия коментар, наистина ви предлагам да използвате индекс "2dsphere" за точно изчисляване на сферично разстояние, както и конвертиране в GeoJSON съхранение за вашето координатно съхранение във вашата база данни Обекти, тъй като и двата са общи стандарти, които произвеждат постоянни резултати.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Търсете множество полета за множество стойности в MongoDB

  2. Как да използвам оптимистично заключване с Spring Data MongoDB?

  3. Как мога да сортирам колекция Meteor по време на вмъкване?

  4. Mongoid:намерете чрез масив от идентификатори

  5. MongoDB агрегат с PHP - групиране по дата