2017-01-13 2 views
1

У меня есть коллекция следующих объектов:сбора переформатирования с использованием агрегации трубопроводы в MongoDB

{ 
    "_did": "213412323234", 
    "metadata": [ 
     { 
     "id": "Language", 
     "value": "EN" 
     }, 
     { 
     "id": "City", 
     "value": "New York" 
     }, 
     { 
     "id": "Gender", 
     "value": "Male" 
     } 
    ] 
} 

После использования некоторых операторов трубопроводов (возможно $ проекта), я ожидал что-то вроде этого:

{ 
    "id": "213412323234", 
    "metadata": { 
    "Language": "EN", 
    "City": "New York", 
    "Gender": "Male" 
    } 
} 
+0

Вы хотите просто $ проектировать данные или преобразовывать данные в БД? – sidgate

+0

db.myCollection.aggregate ({ // все, что вы хотите }) –

+0

Покажите, что вы пробовали. –

ответ

1

Согласно запросу this и его решению новая функция будет добавлена ​​для этой функции - функция называется arrayToObject.

db.foo.aggregate([ 
    {$project: { 
    metadata: { 
     $arrayToObject: { 
     $map: { 
      input: "$metadata", 
      as: "pair", 
      in: ["$$pair.id", "$$pair.value"] 
     } 
     } 
    } 
    }} 
]) 

Но на данный момент, никакого решения. Я предлагаю вам изменить структуру данных. Насколько я вижу, существует множество запросов функций, обозначенных как Major, но не делается в течение многих лет.

1

Попробуйте этот скрипт-запрос

var results = db.meta.aggregate([{ 
    $project: { 
    id: "$_did", 
    _id: 0, 
    keys: "$metadata.id", 
    values: "$metadata.value" 
    } 
}]) 

function object(keys, values) { 
    var obj = {}; 
    for (var index in keys) { 
    obj[keys[index]] = values[index]; 
    } 
    return obj; 
} 

results = results.map(function (res) { 
    return { 
    id: res.id, 
    metadata: object(res.keys, res.values) 
    } 
}) 
3

Если положение элементов в metadata поле и ключи вложенных documens известно, а затем вы можете использовать агрегацию.

db.foo.aggregate([ 
    { 
    $project : { 
     data : { 
     "Language" : { 
      $arrayElemAt : ["$metadata", 0] 
     }, 
     "City" : { 
      $arrayElemAt : ["$metadata", 1] 
     }, 
     "Gender" : { 
      $arrayElemAt : ["$metadata", 2] 
     } 
     } 
    } 
    }, 
    { 
    $project : { 
     metadata : { 
     Language : "$data.Language.value", 
     City : "$data.City.value", 
     Gender : "$data.Gender.value" 
     } 
    } 
    } 
]) 

Результат:

{ "_id" : "213412323234", "metadata" : { "Language" : "EN", "City" : "New York", "Gender" : "Male" } } 

Если какой-либо из указанных выше двух условий, указанных выше, не известны, вы можете использовать mapReduce.

db.foo.mapReduce(function() { 
    var key = this._id; 
    var metadata = this.metadata; 
    var valueEmit = {}; 
    for (var i = 0; i < metadata.length; i++) { 
    valueEmit[metadata[i].id] = metadata[i].value; 
    } 
    emit(key, valueEmit) 
}, 
function(key, values) { 
    // do nothing as it won't be called 
    // for if value is only one 
    // for a key 
}, 
{ 
    out : {replace : "foobar"} 
}) 

Результат:

> db.foobar.find() 
{ "_id" : "213412323234", "value" : { "Language" : "EN", "City" : "New York", "Gender" : "Male" } } 

Обратите внимание, что ключ был изменен на value вместо метаданных. Это можно легко исправить, используя $project в aggregation на коллекции foobar.