コレクションを作成し、このような一意のキーを追加しました
db.user_services.createIndex({"uid":1 , "sid": 1},{unique:true,dropDups: true})
コレクションは次のような「user_services」のようになります
{
"_id" : ObjectId("55068b35f791c7f81000002d"),
"uid" : 15,
"sid" : 1,
"rate" : 5
},
{
"_id" : ObjectId("55068b35f791c7f81000002f"),
"uid" : 15,
"sid" : 1,
"rate" : 4
}
問題:
Phpドライバーを使用して同じidとsidのドキュメントを挿入していますが、挿入されています。
欲しいもの
おめでとうございます。バグを見つけたようです。これは、私のテストではMongoDB 3.0.0でのみ発生するか、少なくともMongoDB 2.6.6では発生しません。 SERVER-17599 にバグが記録されました
[〜#〜]注[〜#〜]:実際には「問題」ではなく、「設計により」確認されています。バージョン3.0.0のオプションを削除しました。 ドキュメント にもリストされています。
問題は、「複合キー」フィールドに既存の重複があるコレクションでこれを作成しようとすると、インデックスが作成されず、エラーが発生することです。上記では、インデックスを作成するとシェルでこれが生成されます。
_{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"errmsg" : "exception: E11000 duplicate key error dup key: { : 15.0, : 1.0 }",
"code" : 11000,
"ok" : 0
}
_
重複が存在しない場合は、現在試行しているインデックスを作成でき、作成されます。
したがって、これを回避するには、最初に次のような手順で重複を削除します。
_db.events.aggregate([
{ "$group": {
"_id": { "uid": "$uid", "sid": "$sid" },
"dups": { "$Push": "$_id" },
"count": { "$sum": 1 }
}},
{ "$match": { "count": { "$gt": 1 } }}
]).forEach(function(doc) {
doc.dups.shift();
db.events.remove({ "_id": {"$in": doc.dups }});
});
db.events.createIndex({"uid":1 , "sid": 1},{unique:true})
_
その後、重複データを含むそれ以上の挿入は挿入されず、適切なエラーが記録されます。
ここでの最後の注意は、「dropDups」は重複データを削除するための非常に洗練されたソリューションではないということです。上で示したように、より詳細な制御が必要です。
2番目の部分では、.insert()
を使用するのではなく、.update()
メソッドを使用します。 "upsert" オプションがあります
_$collection->update(
array( "uid" => 1, "sid" => 1 ),
array( '$set' => $someData ),
array( 'upsert' => true )
);
_
したがって、「見つかった」ドキュメントは「変更」され、見つからなかったドキュメントは「挿入」されます。ドキュメントが実際に挿入されたときにのみ特定のデータを作成し、変更時には作成しない方法については、 _$setOnInsert
_ も参照してください。
特定の試みのために、.update()
の正しい構文は3つの引数です。 「クエリ」、「更新」、「オプション」:
_$collection->update(
array( "uid" => 1, "sid" => 1 ),
array(
'$set' => array( "field" => "this" ),
'$inc' => array( "counter" => 1 ),
'$setOnInsert' => array( "newField" => "another" )
),
array( "upsert" => true )
);
_
「更新」ドキュメントセクションの別の更新操作で使用される「同じパスにアクセス」する更新操作は許可されていません。
現在の最も人気のある答えは、このような基本的なMongoDB操作(キーを使用してmongoから重複を削除する)には少々ローカルで詳細すぎるように感じます。
Mongo> 3.0のキーで重複を削除するのは簡単です。このクエリを実行して、yourDuplicateKey
を置き換え、_id
が主キーです(念のため、mongodumpを使用してください)。
db.yourCollection.aggregate([
{ "$group": {
"_id": { "yourDuplicateKey": "$yourDuplicateKey" },
"dups": { "$Push": "$_id" },
"count": { "$sum": 1 }
}},
{ "$match": { "count": { "$gt": 1 } }}
]).forEach(function(doc) {
doc.dups.shift();
db.yourCollection.remove({ "_id": {"$in": doc.dups }});
});
複数の値を使用して重複レコードを回避するもう1つの簡単な方法
例:次のコードを使用すると、フィールド「学生名」と「親の名前」の重複値を回避できます
$DataForDB = array( "AdmissionNo" => $admissionNo,
"StudentName" => $StudentName, "ParentName" => $ParentName);
if(empty($Coll->findOne(array("StudenName" => $StudentName, "ParentName" => $ParentName)))){
$Coll->insertOne($DataForDB);
}
この場合、次のフィールドを持つドキュメントが存在するかどうかを確認します。存在する場合、データが存在せず、DBにデータが入力されません。