Blahopřejeme, zdá se, že jste našli chybu. To se děje pouze s MongoDB 3.0.0 v mém testování, nebo alespoň není přítomno v MongoDB 2.6.6. Chyba byla nyní zaznamenána na SERVER-17599
POZNÁMKA :Ve skutečnosti to není "problém", ale potvrzeno "by design". Vypustila možnost pro verzi 3.0.0. Stále je však uveden v dokumentaci.
Problém je v tom, že se index nevytváří a při pokusu o jeho vytvoření na kolekci s existujícími duplikáty v polích "složený klíč" dochází k chybám. Ve výše uvedeném případě by vytvoření indexu mělo přinést toto v shellu:
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"errmsg" : "exception: E11000 duplicate key error dup key: { : 15.0, : 1.0 }",
"code" : 11000,
"ok" : 0
}
Pokud nejsou k dispozici žádné duplikáty, můžete vytvořit index tak, jak se právě pokoušíte, a bude vytvořen.
Chcete-li to obejít, nejprve odstraňte duplikáty pomocí tohoto postupu:
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})
Potom nebudou další vložky obsahující duplicitní data vloženy a bude zaznamenána příslušná chyba.
Závěrečná poznámka je, že „dropDups“ je/nebyl příliš elegantním řešením pro odstranění duplicitních dat. Opravdu chcete něco s větší kontrolou, jak je ukázáno výše.
Pro druhou část raději než použijte .insert()
použijte .update()
metoda. Má možnost "upsert"
$collection->update(
array( "uid" => 1, "sid" => 1 ),
array( '$set' => $someData ),
array( 'upsert' => true )
);
Takže „nalezené“ dokumenty se „upraví“ a nenalezené dokumenty se „vloží“. Viz také $setOnInsert
způsob, jak vytvořit určitá data pouze tehdy, když je dokument skutečně vložen, a nikoli při úpravě.
Pro váš konkrétní pokus správná syntaxe .update()
jsou tři argumenty. "query", "update" a "options":
$collection->update(
array( "uid" => 1, "sid" => 1 ),
array(
'$set' => array( "field" => "this" ),
'$inc' => array( "counter" => 1 ),
'$setOnInsert' => array( "newField" => "another" )
),
array( "upsert" => true )
);
Žádná z aktualizačních operací nemá povolen "přístup ke stejné cestě" jako v jiné aktualizační operaci v této sekci dokumentu "aktualizace".