2015-02-22 2 views
0

У меня есть коллекция, которая имеет следующую структуру, как обозначено одним документомДобавление поля массива в коллекцию на основе значений другого поля массива в MongoDB

{ 
_id : 1, 
array1 : [{fld1 : 'doc1e1fld1', fld2: 'doc1e1fld2'},{fld1:'doc1e2fld1',fld2: 'doc1e2fld2'}] 
} 

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

{ 
    _id : 1, 
    array1 : [{fld1 : 'doc1e1fld1', fld2: 'doc1e1fld2'},{fld1:'doc1e2fld1',fld2: 'doc1e2fld2'}], 
    array2 : ['doc1e1fld1','doc1e2fld1'] 
    } 

в основном при добавлении нового элемента массива для всех документов в коллекции и устанавливая его содержимое в массив, который является значением FLD1 всех элементов в массиве 1 документа.

Я посмотрел Update MongoDB field using value of another field, но почему-то я не понимаю, как я могу извлечь только некоторые элементы.

ответ

1

Таким образом, вы должны были понять из вопроса, на который вы ссылались, что при обновлении другого поля вы фактически не ссылаетесь на другое значение, фактически фактически не просматривая документы и не зацикливая результаты для генерации обновлений.

Итак, суть в том, что вы действительно сделали бы это в коде, прочитав каждый документ и извлекая новые значения, из которых будет создан ваш новый массив. Создание этого нового массива можно либо дополнить $set, либо, возможно, безопаснее, используя $push и $each операторов в обновлениях.

В идеале вы также должны использовать Bulk Operations API для получения оптимальной формы обновлений.

Наконец, вы можете также передать часть строительного массива нагрузки на aggregation framework вместо обработки все это в коде клиента, но обновления по-прежнему должны быть выполнены по результатам:

var bulk = db.collection.initializeOrderedBulkOp(); 
var count = 0; 

var cursor = db.collection.aggregate([ 
    { "$project": { 
     "array2": { 
      "$map": { 
       "input": "array1", 
       "as": "el", 
       "in": "$$el.fld1" 
      } 
     } 
    }} 
]); 

cursor.forEach(function(doc) { 
    bulk.find({ "_id": doc._id }).updateOne({ 
     "$push": { "array2": { "$each": doc.array2 } } 
    }); 
    count++; 

    // send and drain once every 1000 documents 
    if (count % 1000 == 0) { 
     bulk.execute(); 
     bulk = db.collection.initializeOrderedBulkOp(); 
    } 
}); 

// If the counter is uneven then send 
if (count % 1000 != 0) 
    bulk.execute(); 

Так там является. Вы можете использовать структуру агрегации с оператором $map, как это, чтобы извлечь требуемые элементы из массива, или просто сделать это в коде с помощью аналогичного метода, учитывая, что вы все равно не «агрегируете» что-либо. Основной случай здесь состоит в том, что вам нужно будет зацикливать результаты в коде, независимо от того, на каком языке вы это делаете.

Конечно, если бы вы могли жить только с созданием «новой» коллекции с измененными результатами, то этап $out трубопровода для агрегата может удовлетворить вас хорошо:

db.collection.aggregate([ 
    { "$project": { 
     "array1": 1, 
     "array2": { 
      "$map": { 
       "input": "array1", 
       "as": "el", 
       "in": "$$el.fld1" 
      } 
     } 
    }}, 
    { "$out": "newcollection" } 
]); 

Короче если вы хотите либо некоторые или все из этих методов, чтобы получить измененную коллекцию результатов вы ищете. Так что либо используйте это прямо, либо реализуйте некоторые из них.

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