Mongo Map-Reduce: группируйте документы на определенном расстоянии по значению - PullRequest
0 голосов
/ 21 мая 2018

Я пытаюсь преобразовать свой запрос агрегации в Map-Reduce один в MongoDB (используя драйвер Ruby).В моем исходном запросе я ищу элементы на определенном расстоянии от точки, а затем группирую их по значению NEIGHBORHOOD.

Образец документа

{
 "_id":"5b01a2c77b61e58732920f86",
 "YEAR":2004,
 "NEIGHBOURHOOD":"Grandview-Woodland",
 "LOC":{"type":"Point","coordinates":[-123.067654,49.26773386]}
}

Запрос агрегации

crime.aggregate([
{ "$geoNear": {
"near": { 
  "type": "Point", 
  "coordinates": [ -123.0837633, 49.26980201 ]
},
"query": { "YEAR": 2004 },
"distanceField": "distance",
"minDistance": 10,
"maxDistance": 10000,
"num": 100000,
"spherical": true
}},
{ "$group": {   
   "_id": "$NEIGHBOURHOOD",
   "count": { "$sum": 1 } 
}}
])

Таким образом, фрагмент вывода выглядит следующим образом:

Вывод

{"_id"=>"Musqueam", "count"=>80}
{"_id"=>"West Point Grey", "count"=>651}
{"_id"=>"Marpole", "count"=>1367}

Теперь я пытаюсь сделать что-то подобное в MapReduce.В моем map function я пытаюсь проверить, находятся ли документы на правильном расстоянии (основываясь на ответе НАСТОЯЩЕГО ВОПРОСА ) и, если это так, передать их reduce function, в котором они будут засчитаны.Но что-то не так, и я не получаю желаемого результата - значения count слишком велики.Что я делаю не так?

Функция карты

 map = "function() {" +
  "var rad_per_deg = Math.PI/180;" +
  "var rm = 6371 * 1000;" +
  "var dlat_rad = (this.LOC.coordinates[0] - (-123.0837633)) * rad_per_deg;" +
  "var dlon_rad = (this.LOC.coordinates[1] - (49.26980201)) * rad_per_deg;" +
  "var lat1_rad = -123.0837633 * rad_per_deg;" +
  "var lon1_rad = 49.26980201 * rad_per_deg;" +
  "var lat2_rad = this.LOC.coordinates[0] * rad_per_deg;" +
  "var lon2_rad = this.LOC.coordinates[1] * rad_per_deg;" +
  "var a = Math.pow(Math.sin(dlat_rad/2), 2) + Math.cos(lat1_rad) * Math.cos(lat2_rad) * Math.pow(Math.sin(dlon_rad/2), 2);" +
  "var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));" +
  "if( rm * c < 10000) { " + 
  " emit(this.NEIGHBOURHOOD, {count: 1});" +
  "}" +
  "};"

Функция уменьшения

reduce = "function(key, values) { " +
  "var sum = 0; " +
  "values.forEach(function(f) { " +
  " sum += f.count; " +
  "}); " +
  "return {count: sum};" +
  "};"

Запрос

 opts =  {
    query:{ "YEAR": 2004 },
    :out => "results", 
    :raw => true
  } 

Выход

 crime.find().map_reduce(map, reduce, opts)

 {"_id"=>"", "value"=>{"count"=>2257.0}}
 {"_id"=>"Arbutus Ridge", "value"=>{"count"=>6066.0}}
 {"_id"=>"Central Business District", "value"=>{"count"=>110947.0}}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...