В MongoDb моего сайта хранится отдельный документ для каждого пользователя. Каждый пользователь будет отвечать на несколько анкетных анкет во время своего визита. Формы хранятся в массиве, но поскольку документы не пересекаются, достаточно одного, единственного документа. Для анализа я хочу составить плоскую таблицу всех ответов по всем формам.Как объединить гетерогенный массив в один документ в MongoDb?
Рассмотрим следующую структуру данных:
{
"USER_SESSION_ID": 456,
"forms": [
{
"age": 21,
"gender": "m"
},
{
"job": "Student",
"years_on_job": "12"
},
{
"Hobby": "Hiking",
"Twitter": "@my_account"
}
]
},
{
"USER_SESSION_ID": 678,
"forms": [
{
"age": 46,
"gender": "f"
},
{
"job": "Bodyguard",
"years_on_job": "2"
},
{
"Hobby": "Skiing",
"Twitter": "@bodyguard"
}
]
}
форм-документы все выглядят по-разному и не имеют конфликтующие поля, поэтому я хотел бы объединить их, получая табличный, плоская структура, как это:
{ 'USER_SESSION_ID': 456, 'age': 21, 'gender': 'm', 'job': 'Student', ... 'Twitter': '@my_account' }
{ 'USER_SESSION_ID': 678, 'age': 46, 'gender': 'f', 'job': 'Bodyguard', ... 'Twitter': '@bodyguard' }
Использование Python, это общая ежу понятно, глядя, как это:
for session in sessions: # Iterate all docs
for form in session['forms']: # Iterate all children
session.update(form) # Integrate to parent doc
del session['forms'] # Remove nested child
В MongoDb я нахожу это довольно трудным для достижения. Я пытаюсь использовать агрегатный трубопровод, который, как я полагаю, должен быть подходящим для этого.
До сих пор я помог себе отвинтив мою структуру данных, как это:
db.sessions.aggregate(
{
'$unwind': '$forms'
},
{
'$project': {
'USER_SESSION_ID': true,
'forms': true
}
},
{
'$group': {
'_id': '$USER_SESSION_ID',
'forms': <magic?!>
}
}
)
В разматывания этапа я создаю документ с данными родителя для каждого ребенка. Это должно быть примерно эквивалентно циклу double-for в моем коде python. Однако то, что я чувствую, что я концептуально отсутствует, является аккумулятором «Слияние» при группировке. В python это делается с dict.update()
, в underscore.js это будет _.extend(destination, *sources)
.
Как достичь этого в MongoDB?
Спасибо за ваш ответ! Мне удалось исправить мою проблему, используя функцию mapReduce, которая позволяет продолжить обработку! Мне нравится, как близко к моему коду Python, но я не знал, что это возможно! Большое спасибо! – cessor
@cessor Не беспокойтесь, рад, что вы нашли решение. – chridam