sql >> Databáze >  >> NoSQL >> MongoDB

MongoDB duplikuje dokumenty i po přidání jedinečného klíče

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".



  1. Má MongoDB nativní rozhraní REST?

  2. MongoDB $filtr

  3. Má Meteor odlišný dotaz na sbírky?

  4. DisabledBackend:Nevyrovnané chování s celerem, Redisem a baňkou