2015-11-25 2 views
1

У нас есть коллекции в следующем форматеMongoDB Еогеасп для вложенной коллекции, чтобы обновить/копировать документы в другую коллекцию

{ 
    "_id" : ObjectId("5640bdec1b988de0be31724e"),  
    "xyz" : "Toshiba Satellite Pro 4600 PIII800", 
    "Manufacture": "Toshiba"  
    "mappingData" : {  
     "title" : "xyz" 
    "brand" : "manufacture"  
    }, 
    "_id" : ObjectId("5640bdec1b9435dfgdf43554b"),  
    "abc" : "Apple Ihone", 
    "mappingData" : {  
     "title" : "abc", 
    "brand" : "Company"   
    } 
} 

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

{ 
"title": "Toshiba Satellite Pro 4600 PIII800", 
"Manufacture":"Toshiba"   
} 

{ 
"title": "Apple Ihone", 
"Manufacture":"Apple"  
} 

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

db.products.find().limit(5).forEach(function(myDoc) { 
    var q = {}; 
    myDoc.mappingData.array.forEach(function(doc){ 
     q[doc]= myDoc[myDoc.mappingData.doc]; 
     }) 
    print(q); 
//q will be inserted to new collection. 



}) 

Возвращение ошибка "TypeError: myDoc.mappingData.array has no properties (shell):3"

Пожалуйста, помогите мне решить эту проблему.

+1

Почему вы используете динамический ключ в своих документах? Это очень плохая идея. – styvane

+0

Именно так поступают данные из источников, и решение запроса будет удалять динамический ключ и иметь прямые данные в другой коллекции. –

+0

Но это не то, о чем вы просите. Вы должны изменить свой вопрос, чтобы сказать, что хотите изменить структуру документов. – styvane

ответ

0

Если вы собираетесь обновить всю коллекцию, тогда limit на вашем курсоре в вашем текущем коде не требуется. Ошибка, которую вы получаете, состоит в том, что поле mappingData в коллекции products не имеет поля подзадачи, которое называется array. Из вашего примера в вопросе доступно только поле поддокумента title, и это тот, который вы хотите.

В зависимости от размера коллекции продуктов вставка преобразованных документов в новую коллекцию может повлиять на ваши операции. Вы можете избежать медленной производительности вставки с использованием нового неупорядоченного bulk insert API, который упрощает операции вставки, отправляя их навалом, и даже лучше, это дает вам реальную обратную связь о том, что удалось и что не удалось.

Следующая основная операция вставки API, будет вставлять в newcollection нужную структуру данных, где новые документы создаются в рамках forEach() цикла продуктов, коллекции курсора, используя bracket notation, чтобы создать новые свойства. В массовой вставке, вы будете отправлять операции на сервер в партиях от 1000, которая дает вам лучшую производительность, как вы не отправляете каждый запрос на сервер, только один раз в каждых 1000 запросах:

var bulk = db.newcollection.initializeUnorderedBulkOp(), 
    counter = 0; 

db.products.find().forEach(function(doc) { 
    var document = {}; 
    if (doc.mappingData.title) document["title"] = doc[doc.mappingData.title]; 
    document["Manufacturer"] = doc.Manufacture; 
    bulk.insert(document); 
    counter++; 
    if (counter % 1000 == 0) { 
     bulk.execute(); 
     bulk = db.newcollection.initializeUnorderedBulkOp(); 
    } 
}); 

if (counter % 1000 != 0) { bulk.execute(); } 

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

BulkWriteResult({ 
    "writeErrors" : [ ], 
    "writeConcernErrors" : [ ], 
    "nInserted" : 2, 
    "nUpserted" : 0, 
    "nMatched" : 0, 
    "nModified" : 0, 
    "nRemoved" : 0, 
    "upserted" : [ ] 
}) 

запрашивая новую коллекцию db.newcollection.find() даст:

/* 0 */ 
{ 
    "_id" : ObjectId("56558b0427adb60c9f7e6f8d"), 
    "title" : "Toshiba Satellite Pro 4600 PIII800", 
    "Manufacturer" : "Toshiba" 
} 

/* 1 */ 
{ 
    "_id" : ObjectId("56558b0427adb60c9f7e6f8e"), 
    "title" : "Apple Ihone", 
    "Manufacturer" : undefined 
} 
+0

Спасибо, Chridam для вас превосходное решение. Могу ли я увеличить счетчик от 1000 до 10000, чтобы повысить производительность? –

+0

В документации [** **] (https://docs.mongodb.org/manual/reference/limits/#Write-Command-Operation-Limit-Size) команды _Write могут принимать не более 1000 операций.Операции Bulk() в оболочке mongo и сопоставимые методы в драйверах не имеют этого предела, но реальным пределом здесь является предел BSON на 16 МБ, поскольку это будет максимальный размер того, что может быть отправлено по проводу, как то, что эффективно один документ BSON. В идеале вы бы хотели иметь меньшие управляемые куски, которые не слишком велики по сети и, безусловно, безопасны под 16 МБ. – chridam

+0

Также ознакомьтесь с этим [** JIRA ticket **] (https://jira.mongodb.org/browse/DOCS-3603) – chridam