修复 MongoDB 中包含相同字段的记录
fix records that contain the same field in MongoDB
由于系统错误,创建了不正确的记录。
当前:
{
"_id" : ObjectId("5cb48b1875aca0626d0272db"),
"similiarModels" : [
ObjectId("5cb48b1875aca0626d0272db"), -> the same as the _id field of the object, it must be removed from the array
ObjectId("9fg48f5325qwa0436h9433ae")
]
"topModel" : ObjectId("5cb48b1875aca0626d0272db") -> the same as the _id field of the object, should be removed
}
我要:
{
"_id" : ObjectId("5cb48b1875aca0626d0272db"),
"similiarModels" : [
ObjectId("9fg48f5325qwa0436h9433ae")
]
}
这是一个解决方案。注意管道形式 update
和 $$REMOVE
特殊值的使用。
db.foo.update(
{}, // no filter; get all docs
[ // use pipeline form of update expression for greater flexibility!
{$set: {
'similarModels': {$setDifference:['$similarModels', ['$_id'] ]},
'topModel': {$cond: [
{$eq:['$topModel','$_id']}, // if
'$$REMOVE', // then get rid of field
'$topModel' // else set it back to original
]}
}}
],
{multi:true}
);
或者,可以使用 v4.4 中引入的“合并到自身”功能。这让aggregate
可以充当巨人update
。请参阅以下评论中的警告:
db.foo.aggregate([
// EXACT same expression as pipeline update above; nice.
{$set: {
'similarModels': {$setDifference: ['$similarModels', ['$_id'] ]},
'topModel': {$cond: [
{$eq:['$topModel','$_id']}, // if
'$$REMOVE', // then get rid of field
'$topModel' // else set it back to original
]}
}},
// Sadly, the whenMatched:'merge' option will not "unset" fields; it only
// adds or overwrites fields so this approach will not work for $topModel field.
// We can, however, use whenMatched:'replace' but this might present
// a performance issue because the entire doc, not just similarModels
// and topModel, is being written back.
{$merge: {
into: "foo",
on: [ "_id" ],
whenMatched: "replace",
whenNotMatched: "fail"
}}
]);
由于系统错误,创建了不正确的记录。
当前:
{
"_id" : ObjectId("5cb48b1875aca0626d0272db"),
"similiarModels" : [
ObjectId("5cb48b1875aca0626d0272db"), -> the same as the _id field of the object, it must be removed from the array
ObjectId("9fg48f5325qwa0436h9433ae")
]
"topModel" : ObjectId("5cb48b1875aca0626d0272db") -> the same as the _id field of the object, should be removed
}
我要:
{
"_id" : ObjectId("5cb48b1875aca0626d0272db"),
"similiarModels" : [
ObjectId("9fg48f5325qwa0436h9433ae")
]
}
这是一个解决方案。注意管道形式 update
和 $$REMOVE
特殊值的使用。
db.foo.update(
{}, // no filter; get all docs
[ // use pipeline form of update expression for greater flexibility!
{$set: {
'similarModels': {$setDifference:['$similarModels', ['$_id'] ]},
'topModel': {$cond: [
{$eq:['$topModel','$_id']}, // if
'$$REMOVE', // then get rid of field
'$topModel' // else set it back to original
]}
}}
],
{multi:true}
);
或者,可以使用 v4.4 中引入的“合并到自身”功能。这让aggregate
可以充当巨人update
。请参阅以下评论中的警告:
db.foo.aggregate([
// EXACT same expression as pipeline update above; nice.
{$set: {
'similarModels': {$setDifference: ['$similarModels', ['$_id'] ]},
'topModel': {$cond: [
{$eq:['$topModel','$_id']}, // if
'$$REMOVE', // then get rid of field
'$topModel' // else set it back to original
]}
}},
// Sadly, the whenMatched:'merge' option will not "unset" fields; it only
// adds or overwrites fields so this approach will not work for $topModel field.
// We can, however, use whenMatched:'replace' but this might present
// a performance issue because the entire doc, not just similarModels
// and topModel, is being written back.
{$merge: {
into: "foo",
on: [ "_id" ],
whenMatched: "replace",
whenNotMatched: "fail"
}}
]);