2015-06-07 2 views
0

хочет обновить свой оригинал документа в документ ожидаемыхКак я могу обновить конкретные дублированные элементы в массиве

То есть удалить дублированный подряд же ценовой рекорд,

только держать последнюю.

Как это сделать с запросом манго?

Ожидаемый документ

{ 
    "_id": "2015-06-12-TPE-KIX", 
    "flight_date": new Date("2015-06-12T08:00:00+0800"), 
    "history": [ 
    { 
     "updated_at": new Date(1433515526965), 
     "price": 6740 
    }, 
    { 
     "updated_at": new Date(1433607771762), 
     "price": 5490 
    } 
    ] 
} 

Оригинал документа

{ 
    "_id": "2015-06-12-TPE-KIX", 
    "flight_date": new Date("2015-06-12T08:00:00+0800"), 
    "history": [ 
    { 
     "updated_at": new Date(1433492046834), 
     "price": 6740 
    }, 
    { 
     "updated_at": new Date(1433492048208), 
     "price": 6740 
    }, 
    { 
     "updated_at": new Date(1433492428642), 
     "price": 6740 
    }, 
    { 
     "updated_at": new Date(1433492430039), 
     "price": 6740 
    }, 
    { 
     "updated_at": new Date(1433515526965), 
     "price": 6740 
    }, 
    { 
     "updated_at": new Date(1433562561356), 
     "price": 5490 
    }, 
    { 
     "updated_at": new Date(1433603772299), 
     "price": 5490 
    }, 
    { 
     "updated_at": new Date(1433607771762), 
     "price": 5490 
    } 
    ] 
} 

ответ

1

Ну вы могли бы использовать структуру агрегации в качестве средства для уменьшения массива необходимых элементов, а затем обновлять каждый документ в коллекции с результатами. Пример Shell только, но та же базовая логика применяется:

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

db.collection.aggregate([ 
    // Unwind the array 
    { "$unwind": "$history" }, 

    // Group by price on each document 
    { "$group": { 
     "_id": { 
      "_id": "$_id", 
      "flight_date": "$flight_date", 
      "price": "$history.price" 
     }, 
     "updated_at": { "$max": "$history.updated_at" } 
    }}, 

    // Sort by updated_at in each document 
    { "$sort": { "_id._id": 1, "updated_at": 1 } }, 

    // Group back per document 
    { "$group": { 
     "_id": "$_id._id", 
     "flight_date": { "$first": "$_id.flight_date" }, 
     "history": { 
      "$push": { 
       "updated_at": "$updated_at", 
       "price": "$_id.price" 
      } 
     } 
    }} 
]).forEach(function(doc) { 
    bulk.find({ "_id": doc._id }).updateOne({ 
     "$set": { "history": doc.history } 
    }); 
    count++; 

    // Send to server every 1000 and re-init 
    if (count % 1000 == 0) { 
     bulk.execute(); 
     bulk = db.collection.initializeOrderedBulkOp(); 
    } 
}); 

// Process any queued 
if (count % 1000 != 0) 
    bulk.execute(); 

Так что уменьшает вниз массив в результатах, что вы хотите выглядеть примерно так:

{ 
    "_id" : "2015-06-12-TPE-KIX", 
    "flight_date" : ISODate("2015-06-12T00:00:00Z"), 
    "history" : [ 
      { 
        "updated_at" : ISODate("2015-06-05T14:45:26.965Z"), 
        "price" : 6740 
      }, 
      { 
        "updated_at" : ISODate("2015-06-06T16:22:51.762Z"), 
        "price" : 5490 
      } 
    ] 
} 

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

Операция $unwind имеет значительные накладные расходы по сравнению с коллекцией документов, и поскольку вы на самом деле не «агрегируете» по документам, подход к управлению вашим массивом в клиентском коде был бы наиболее эффективной задачей.

Конечно, если вы можете жить с новой коллекцией или счастливы переименовать коллекции, используйте опцию $out с агрегацией, как показано выше.

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