Вам потребуется механизм, чтобы получить все динамические ключи, которые вам необходимо собрать динамический $project
документ. Это возможно через Map-Reduce. Следующая операция MapReduce будет заполнять отдельную коллекцию со всеми ключами как _id
значения:
mr = db.runCommand({
"mapreduce": "my_collection",
"map" : function() {
for (var key in this.subdoc) { emit(key, null); }
},
"reduce" : function(key, stuff) { return null; },
"out": "my_collection" + "_keys"
})
Чтобы получить список всех динамических ключей, запустите отличие от полученной коллекции:
db[mr.result].distinct("_id")
["field2", "field3", ...]
сейчас учитывая приведенный выше список, вы можете собрать свой документ конвейера агрегации, создав объект, который будет иметь свои свойства, заданные в цикле. Обычно ваш $project
документ будет иметь такую структуру:
var project = {
"$project": {
"field1": 1,
"field2": "$subdoc.field2",
"field3": "$subdoc.field3"
}
};
Таким образом, используя приведенный выше список ключей поддокументе, вы можете динамически построить выше, используя reduce()
метод в JavaScript:
var subdocKeys = db[mr.result].distinct("_id"),
obj = subdocKeys.reduce(function (o, v){
o[v] = "$subdoc." + v;
return o;
}, { "field1": 1 }),
project = { "$project": obj };
db.collection.aggregate([project]);
Вы должны были бы используйте Map-Reduce сначала, чтобы получить ключи для поддокумента, затем постройте документ '$ project', используя динамически возвращаемые ключи. – chridam
@chridam вы можете привести пример для схемы выше? – TomG
Я привел пример в ответе ниже. – chridam