#mongodb #aggregation-framework
#mongodb #структура агрегации
Вопрос:
У меня есть набор документов в mongodb, и я пытаюсь сгруппировать набор документов, используя ближайшие координаты геопункта на расстоянии 100 м в радиусе до данного документа, и получить среднее значение type
и $first
значение для cordinates
. Образец набора документов приведен ниже. Есть ли способ сделать это, используя существующие функции в конвейере агрегации mongodb, или мне нужно использовать недавно введенные $function
для создания пользовательской функции агрегации. Любые предложения приветствуются.
{"_id":{"$oid":"5e790cfe46fa8260f41d2626"},
"cordinates":[103.96277219999999,1.3437526],
"timestamp":1584991486436,
"user":{"$oid":"5e4bbbc31eac8e2e3ca219a6"},
"type": 1,
"__v":0}
{"_id":{"$oid":"5e790d7346fa8260f41d2627"},
"cordinates":[103.97242539965999,1.33508],
"timestamp":1584991603400,
"user":{"$oid":"5e4bbbc31eac8e2e3ca219a6"},
"type": 1,
"__v":0}
{"_id":{"$oid":"5e790d7346fa8260f41d2627"},
"cordinates":[103.97242539990099,1.33518],
"timestamp":1584991603487,
"user":{"$oid":"5e4bbbc31eac8e2e3ca219a6"},
"type": 2,
"__v":0}
Образец документа, который ожидается в качестве вывода после конвейера агрегации.
{"avgCordinates":[103.97242539990099,1.33518],
"avgType": 1.6,
}
Ответ №1:
Мне удалось решить эту проблему, создав пользовательскую функцию для представления одного значения для геопространственной координаты, а затем сгруппировав по возвращаемым значениям. Я смог сгруппировать близлежащие координаты в один документ, поскольку функция, которую я использовал для преобразования значений, также будет сопоставляться с близлежащими скалярными значениями. До сих пор это давало мне ожидаемые результаты для тепловой карты. Но все же я не уверен, что это правильный способ сделать это. Для этого должен быть лучший ответ. Я опубликовал свой конвейер агрегации ниже. Приветствуются любые предложения по улучшению этого.
[
{
'$match': {
'timestamp': {
'$gte': 1599889338000
}
}
}, {
'$addFields': {
'singleCoordinate': {
'$function': {
'body': 'function(coordinates){return ((coordinates[1] 90)*180 coordinates[0])*1000000000000;}',
'args': [
'$coordinates', '$geonear'
],
'lang': 'js'
}
}
}
}, {
'$group': {
'_id': {
'$subtract': [
'$singleCoordinate', {
'$mod': [
'$singleCoordinate', 100
]
}
]
},
'coordinates': {
'$first': '$coordinates'
},
'avgType': {
'$avg': '$type'
}
}
}, {
'$addFields': {
'latitude': {
'$arrayElemAt': [
'$coordinates', 1
]
},
'longitude': {
'$arrayElemAt': [
'$coordinates', 0
]
},
'weight': {
'$multiply': [
'$avgType', '$_id'
]
}
}
}, {
'$project': {
'_id': false,
'coordinates': false,
'avgType': false
}
}
]