MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

Dokumen Duplikat MongoDB bahkan setelah menambahkan kunci unik

Selamat, Anda tampaknya telah menemukan bug. Ini hanya terjadi dengan MongoDB 3.0.0 dalam pengujian saya, atau setidaknya tidak ada di MongoDB 2.6.6. Bug sekarang tercatat di SERVER-17599

CATATAN :Sebenarnya bukan "masalah" tetapi dikonfirmasi "dengan desain". Menjatuhkan opsi untuk versi 3.0.0. Masih tercantum dalam dokumentasi.

Masalahnya adalah indeks tidak dibuat dan kesalahan saat Anda mencoba membuat ini pada koleksi dengan duplikat yang ada di bidang "kunci majemuk". Di atas, pembuatan indeks harus menghasilkan ini di shell:

{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "errmsg" : "exception: E11000 duplicate key error dup key: { : 15.0, : 1.0 }",
    "code" : 11000,
    "ok" : 0
}

Ketika tidak ada duplikat, Anda dapat membuat indeks seperti yang sedang Anda coba dan indeks itu akan dibuat.

Jadi untuk mengatasinya, hapus dulu duplikatnya dengan prosedur seperti ini:

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})

Kemudian penyisipan lebih lanjut yang berisi data duplikat tidak akan dimasukkan dan kesalahan yang sesuai akan dicatat.

Catatan terakhir di sini adalah bahwa "dropDups" bukanlah solusi yang sangat elegan untuk menghapus data duplikat. Anda benar-benar menginginkan sesuatu dengan kontrol lebih seperti yang ditunjukkan di atas.

Untuk bagian kedua, daripada menggunakan .insert() gunakan .update() metode. Ini memiliki opsi "upser"

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

Jadi dokumen yang "ditemukan" "dimodifikasi" dan dokumen yang tidak ditemukan "dimasukkan". Lihat juga $setOnInsert cara untuk hanya membuat data tertentu saat dokumen benar-benar dimasukkan dan bukan saat diubah.

Untuk upaya spesifik Anda, sintaks yang benar dari .update() adalah tiga argumen. "kueri", "perbarui" dan "opsi":

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

Tidak ada operasi pembaruan yang diizinkan untuk "mengakses jalur yang sama" seperti yang digunakan dalam operasi pembaruan lain di bagian dokumen "pembaruan".



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Mencari di mongo db menggunakan regex luwak vs. teks

  2. Memuat sebagian gagal di server JS

  3. Permintaan Mongodb berdasarkan item pada posisi tertentu dalam array

  4. MongoDB Tampilkan Pengguna Saat Ini

  5. Operator Kueri $type MongoDB