php - MongoDB Duplicate Documents even after adding unique key -


i have created collection , added unique key

db.user_services.createindex({"uid":1 , "sid": 1},{unique:true,dropdups: true}) 

the collection looks "user_services"

{  "_id" : objectid("55068b35f791c7f81000002d"),  "uid" : 15,  "sid" : 1,  "rate" : 5 }, {   "_id" : objectid("55068b35f791c7f81000002f"),  "uid" : 15,  "sid" : 1,  "rate" : 4 } 

problem :

am using php driver insert documents same uid , sid , getting inserted.

what want

  1. on mongo shell : add unique key on uid , sid no duplicate documents same uid , sid.
  2. on php side : having mysql "insert (value) on duplicate key update rate=rate+1". whenever try insert document, should inserted if not there else should update rate field of document

congratulations, appear have found bug. happens mongodb 3.0.0 in testing, or @ least not present @ mongodb 2.6.6. bug recorded @ server-17599

note: not "issue" confirmed "by design". dropped option version 3.0.0. still listed in documentation though.

the problem index not being created , errors when attempt create on collection existing duplicates on "compound key" fields. on above, index creation should yield in shell:

{     "createdcollectionautomatically" : false,     "numindexesbefore" : 1,     "errmsg" : "exception: e11000 duplicate key error dup key: { : 15.0, : 1.0 }",     "code" : 11000,     "ok" : 0 } 

when there no duplicates present can create index trying , created.

so work around this, first remove duplicates procedure this:

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

then further inserts containing duplicate data not inserted , appropriate error recorded.

the final note here "dropdups" is/was not elegant solution removing duplicate data. want more control demonstrated above.

for second part, rather use .insert() use .update() method. has "upsert" option

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

so "found" documents "modified" , documents not found "inserted". see $setoninsert way create data when document inserted , not when modified.


for specific attempt, correct syntax of .update() 3 arguments. "query", "update" , "options":

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

none of update operations allowed "access same path" used in update operation in "update" document section.


Comments

Popular posts from this blog

Is there a better way to structure post methods in Class Based Views -

performance - Why is XCHG reg, reg a 3 micro-op instruction on modern Intel architectures? -

jquery - Responsive Navbar with Sub Navbar -