2016-10-31 3 views
0

У меня много дубликатов записей в моей базе данных Mongo. Есть ли быстрый способ удалить эти дубликаты? Я заинтересован в двух различных сценариях:MongoDB: падение дубликатов на основе полей

  1. Для повторяющихся записей каждого из полей равны (кроме ObjectID)

  2. Для повторяющихся записей только подмножество всех полей равны. В этом случае я хотел бы указать эти поля и удалить дубликаты на их основе.

Что такое «монгойский» способ сделать это?

Пример запись будет:

{ 
"_id" : ObjectId("57294d7071f55974cdae318e"), 
"category" : "house", 
"city" : "Boston", 
"title" : "title here", 
"url" : "http://url.com", 
"text" : " some text here", 
"time" : ISODate("2016-05-03T23:49:00Z"), 
"user_online_since" : ISODate("2012-10-01T00:00:00Z"), 
"price_eur" : 85000 
} 
+0

Просьба представить некоторые образцы документов и результатов вы ожидаете – felix

ответ

1

здесь есть JS скрипт, который вы можете использовать для достижения этой цели:

var matchingId = []; 

db.collectionName.aggregate([ 
    { 
     // group stage: group document by field 
     // this return one document per unique value 
     $group:{ 
     _id:{ 
      category:"$category", 
      city:"$city" 
     // ... 
     // here add as many field as you want for duplicate check 
     }, 
     // this field count the number of documents having the same 
     // values for the selected fields 
     count:{ 
      $sum:1 
     }, 
     // this field store the _id of documents that have the same 
     // value for selected fields 
     match:{ 
      $push:"$_id" 
     } 
     } 
    }, 
    { 
     // only keep documents where count > 1 
     $match:{ 
     count:{ 
      $gt:1 
     } 
     } 
    }], 
    { 
     // allow mongoDB to write to disk if your collection is too big 
     allowDiskUse: true 
    } 
).forEach(function(doc) { 
    doc.match.shift(); // remove the first objectId 
    doc.match.forEach(function(duplicateId) { 
    matchingId.push(duplicateId); 
    }); 
}); 

// remove duplicate documents 
db.collectionName.remove({_id: {$in: matchingId}}) 

использовать его написать это в файл с именем «script.js» и использовать его как это с вашего терминала:

mongo databaseName < script.js 

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

редактировать: пример

скажем ваша коллекция выглядит

{ 
    "_id" : ObjectId("57294d7071f55974cdae318e"), 
    "category" : "house", 
    "city" : "Boston", 
    "title" : "title here", 
    "url" : "http://url.com", 
    "text" : " some text here", 
    "time" : ISODate("2016-05-03T23:49:00Z"), 
    "user_online_since" : ISODate("2012-10-01T00:00:00Z"), 
    "price_eur" : 85000 
} 
{ 
    "_id" : ObjectId("57294d7071f55974cdae318b"), 
    "category" : "house", 
    "city" : "NY", 
    "title" : "title here", 
    "url" : "http://url.com", 
    "text" : " some text here", 
    "time" : ISODate("2016-05-03T23:49:00Z"), 
    "user_online_since" : ISODate("2012-10-01T00:00:00Z"), 
    "price_eur" : 85000 
} 
{ 
    "_id" : ObjectId("57294d7071f55974cdae318f"), 
    "category" : "house", 
    "city" : "Boston", 
    "title" : "title here", 
    "url" : "http://url.com", 
    "text" : " some text here", 
    "time" : ISODate("2016-05-03T23:49:00Z"), 
    "user_online_since" : ISODate("2012-10-01T00:00:00Z"), 
    "price_eur" : 85000 
} 
{ 
    "_id" : ObjectId("57294d7071f55974cdae318c"), 
    "category" : "house", 
    "city" : "Boston", 
    "title" : "title here", 
    "url" : "http://url.com", 
    "text" : " some text here", 
    "time" : ISODate("2016-05-03T23:49:00Z"), 
    "user_online_since" : ISODate("2012-10-01T00:00:00Z"), 
    "price_eur" : 85000 
} 

выход запроса агрегации будет

{ 
    "_id" : { 
     "category" : "house", 
     "city" : "Boston" 
    }, 
    "count" : 3, 
    "match" : [ 
     ObjectId("57294d7071f55974cdae318e"), 
     ObjectId("57294d7071f55974cdae318f"), 
     ObjectId("57294d7071f55974cdae318c") 
    ] 
} 

так что вы итерацию по результатам и для каждого документы вы удаляете первый _id (так как вам нужно сохранить один документ среди дубликатов) с match.shift() , а затем хранить другие _ids, так что вы можете удалить соответствующие документы

после выполнения сценария коллекция содержит только те документы

{ 
    "_id" : ObjectId("57294d7071f55974cdae318e"), 
    "category" : "house", 
    "city" : "Boston", 
    "title" : "title here", 
    "url" : "http://url.com", 
    "text" : " some text here", 
    "time" : ISODate("2016-05-03T23:49:00Z"), 
    "user_online_since" : ISODate("2012-10-01T00:00:00Z"), 
    "price_eur" : 85000 
} 
{ 
    "_id" : ObjectId("57294d7071f55974cdae318b"), 
    "category" : "house", 
    "city" : "NY", 
    "title" : "title here", 
    "url" : "http://url.com", 
    "text" : " some text here", 
    "time" : ISODate("2016-05-03T23:49:00Z"), 
    "user_online_since" : ISODate("2012-10-01T00:00:00Z"), 
    "price_eur" : 85000 
} 
+0

спасибо. Не могли бы вы немного объяснить, что происходит? – Botond

+0

@Botond см. Мое редактирование – felix

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