考慮使用聚合框架來識別重複文檔,獲取actors集合旁的actors集合副本_ids
的列表,並以ids數組作爲查詢來發出刪除和更新命令。
出於測試目的,假設您在您的收藏以下數據(最低試驗情況下,當然演示目的):
db.movies.insert([
{
"_id" : ObjectId("5543e79e42063d2be5d2ea84"),
"id" : 1,
"genres" : []
},
{
"_id" : ObjectId("5543e79e42063d2be5d2ea85"),
"id" : 2,
"genres" : []
},
{
"_id" : ObjectId("5543e79e42063d2be5d2ea86"),
"id" : 3,
"genres" : []
}
]);
db.actors.insert([
{ id: 1, known_for: [ObjectId("5543e79e42063d2be5d2ea84")] },
{ id: 1, known_for: [ObjectId("5543e79e42063d2be5d2ea84")] },
{ id: 2, known_for: [ObjectId("5543e79e42063d2be5d2ea84"), ObjectId("5543e79e42063d2be5d2ea85")] },
{ id: 3, known_for: [ObjectId("5543e79e42063d2be5d2ea85"), ObjectId("5543e79e42063d2be5d2ea86")] }
]);
現在到了神奇的一部分。聚合管道將演員文檔按id
分組,計算分組計數,創建兩個數組字段,用於保存演員_id
重複項和電影對象ID。這條管道將結果輸出到集合愚弄稍後將在用於去除重複:
db.actors.aggregate([
{
"$group": {
"_id": "$id",
"duplicates": { "$addToSet": "$_id" },
"movies": { "$addToSet": "$known_for"},
"count": { "$sum": 1 }
}
},
{
"$match": {
"count": { "$gt": 1 }
}
},
{
"$out": "dupes"
}
])
詢問受騙者集合會給結果:
/* 1 */
{
"_id" : 1.0000000000000000,
"duplicates" : [
ObjectId("5543fc8e42063d2be5d2eaa2"),
ObjectId("5543fc8e42063d2be5d2eaa1")
],
"movies" : [
[
ObjectId("5543e79e42063d2be5d2ea84")
]
],
"count" : 2
}
現在最有趣的部分。使用系列集合,然後從演員集合中刪除該系列。正如你從受騙者集合注意到,在電影字段是一個數組的數組,所以你需要將其鋪平,用扁平陣列,然後再消除電影和拉從演員集合孤立的電影引用:
db.dupes.find({}).find({}).forEach(function (doc) {
var movie_dupes = [];
db.actors.remove({ "_id": { "$in": doc.duplicates } });
doc.movies.forEach(function (arr){
arr.forEach(function (id){
movie_dupes.push(id)
});
});
db.movies.remove({ "_id": { "$in": movie_dupes } });
db.actors.update({ "known_for": { "$in": movie_dupes } }, { "$pull": { "known_for": { "$in": movie_dupes } } }, { "multi": true });
});
日誌安慰:
Removed 2 record(s) in 38ms
Removed 1 record(s) in 2ms
Updated 1 existing record(s) in 1ms
我們驗證我們的重複是否被沖掉:
db.actors.find()
/* 1 */
{
"_id" : ObjectId("5543fc8e42063d2be5d2eaa3"),
"id" : 2,
"known_for" : [
ObjectId("5543e79e42063d2be5d2ea85")
]
}
/* 2 */
{
"_id" : ObjectId("5543fc8e42063d2be5d2eaa4"),
"id" : 3,
"known_for" : [
ObjectId("5543e79e42063d2be5d2ea85"),
ObjectId("5543e79e42063d2be5d2ea86")
]
}
演員id
1(這是一個副本)確實被刪除。
db.movies.find()
/* 1 */
{
"_id" : ObjectId("5543e79e42063d2be5d2ea85"),
"id" : 2,
"genres" : []
}
/* 2 */
{
"_id" : ObjectId("5543e79e42063d2be5d2ea86"),
"id" : 3,
"genres" : []
}
電影ObjectId("5543e79e42063d2be5d2ea84")
被刪除。
要清楚,你想級聯刪除存儲在Actor記錄的'known_for'數組中的ObjectIds的相關電影記錄?在這種情況下,任何引用該Movie的其他Actor將在其「known_for」數組中擁有一個孤立的ID。你是否總是想要執行這個邏輯,或者只是爲了有'id'值重複的Actor? –