MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

MongoDB Дублиращи се документи дори след добавяне на уникален ключ

Поздравления, изглежда сте открили грешка. Това се случва само с 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" е/не е много елегантно решение за премахване на дублиращи се данни. Наистина искате нещо с повече контрол, както е показано по-горе.

За втората част, вместо да използвате .insert() използвайте .update() метод. Има опция "upsert"

$collection->update(
    array( "uid" => 1, "sid" => 1 ),
    array( '$set' => $someData ),
    array( 'upsert' => true )
);

Така „намерените“ документи се „модифицират“, а неоткритите се „вмъкват“. Вижте също $setOnInsert за начин да създавате определени данни само когато документът действително е вмъкнат, а не когато е променен.

За вашия конкретен опит, правилният синтаксис на .update() е три аргумента. "заявка", "актуализация" и "опции":

$collection->update(
    array( "uid" => 1, "sid" => 1 ),
    array(
        '$set' => array( "field" => "this" ),
        '$inc' => array( "counter" => 1 ),
        '$setOnInsert' => array( "newField" => "another" )
   ),
   array( "upsert" => true )
);

Нито една от операциите за актуализиране няма право да „достъп до същия път“, както се използва при друга операция за актуализиране в този раздел на документа „актуализация“.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. db.collection не е функция, когато използвате MongoClient v3.0

  2. NodeJS и MongoDB FindAndModify() трябва да бъдат премахнати или актуализирани

  3. pymongo:MongoClient или Connection

  4. Mongoose с mongodb как да върна току-що запазен обект?

  5. Управление на MySQL, MongoDB и PostgreSQL с ChatOps от Slack