2015-04-24 3 views
3

Я пытаюсь использовать агрегированные структуру MongoDB для генерации документов из коллекции, которая имеет следующую структуру:MongoDB: Итоговые значения всех полей определенного поддокументе

{ 
    "_id" : ObjectId("5510eb56f877bbef153d236d"), 
    "attributes" : { 
    "brand" : "Mercedes", 
    "price" : 289, 
    "family" : "GARDEN" 
    }, 
    "name" : "Bigger Fix Soft Crisps" 
} 
{ 
    "_id" : ObjectId("5510eb56f877bbef153d236e"), 
    "attributes" : { 
    "brand" : "Adelholzener", 
    "price" : 683, 
    "family" : "COMPUTER" 
    }, 
    "name" : "Soft Stockhome Chips" 
} 
{ 
    "_id" : ObjectId("5510eb56f877bbef153d236f"), 
    "attributes" : { 
    "brand" : "Pepsi", 
    "price" : 789, 
    "family" : "CAR" 
    }, 
    "name" : "Light Yearsailfresh Meat" 
} 

Я хочу, чтобы получить агрегацию все поля из подкаталога attributes с их возможными значениями. Поскольку поля в поддоку не известны, я не могу просто использовать поля, приведенные в этом примере, и поэтому должен быть динамическим. Результат должен выглядеть примерно так:

{ 
    "_id" : "brand", 
    "values" : [ 
    "Mercedes", "Adelholzener", "Pepsi" 
    ] 
}, 
{ 
    "_id" : "price", 
    "values" : [ 
    289, 683, 789 
    ] 
}, 
{ 
    "_id" : "family", 
    "values" : [ 
    "GARDEN", "COMPUTER", "CAR" 
    ] 
} 

Я пока не нашел решение этой проблемы. Я пробовал с $project и $unwind (что, очевидно, работает только для массивов).

+0

вы можете сказать о коллекции? –

+1

Возможно, вам следует использовать три отдельных агрегата, чтобы узнать «бренд», «цена» и «семейство», другое разумное использование карты уменьшить – Yogesh

ответ

1

Попытался выяснить, как это сделать, заполнить, но я не уверен, что это возможно, поскольку вы не можете получить ключи в объекте любым удобным способом.

Вот MapReduce работа, которая делает вещь:

db.runCommand({ 
    "mapreduce" : "test_collection", // Change collection here 
    "map" : function() { 
    for (var key in this.attributes) { 
     // Emit objects w array as we cannot reduce arrays directly 
     emit(key, {x: [this.attributes[key]]}); 
    } 
    }, 
    "reduce" : function(key, values) { 
    var res = []; 
    values.forEach(function (d) { 
     Array.prototype.push.apply(res, d.x);   
    }); 
    return {x: res}; 
    }, 
    "finalize": function (key, reducedVal) { 
    return reducedVal.x; 
    }, 
    "out": { inline: 1 } 
}); 
+0

Это действительно работает, но, как вы заявили, вероятно, нет * приятного * способа получить ключи образуют объект. Спасибо! – fdomig

Смежные вопросы