即使添加了唯一密钥,MongoDB也会复制文档 [英] MongoDB Duplicate Documents even after adding unique key

查看:68
本文介绍了即使添加了唯一密钥,MongoDB也会复制文档的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经创建了一个集合,并添加了一个像这样的唯一键

I have created a collection and added a unique key like this

db.user_services.createIndex({"uid":1 , "sid": 1},{unique:true,dropDups: true})

该收藏集看起来像这样 "user_services"

The collection looks something like this "user_services"

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

 "_id" : ObjectId("55068b35f791c7f81000002f"),
 "uid" : 15,
 "sid" : 1,
 "rate" : 4
}

问题:

Am使用php驱动程序插入具有相同 uid和sid 的文档,并且该文档正在被插入.

Am using php driver to insert documents with same uid and sid and it is getting inserted.

我想要的

  1. 在Mongo Shell上:在uid和sid上添加唯一键,没有重复的文档具有相同的uid和sid.
  2. 在PHP方面:具有类似mysql 在重复键更新率= rate + 1上插入(值)"之类的东西.就是说,每当我尝试插入文档时,如果没有插入文档,都应将其插入,否则它将更新文档的费率字段
  1. On Mongo Shell : Add unique key on uid and sid with no duplicate documents with the same uid and sid.
  2. On PHP Side : having something like mysql "insert (value) on duplicate key update rate=rate+1". That is whenever I try to insert a document, it should be inserted if not there else it should update the rate field of the document

推荐答案

恭喜,您似乎发现了一个错误.这仅在我的测试中使用MongoDB 3.0.0发生,或者至少在MongoDB 2.6.6中不存在.错误现已记录在 SERVER-17599

注意: 实际上不是问题",而是设计使然".删除了版本3.0.0的选项.不过,仍在文档中列出. /p>

NOTE: Not actually an "issue" but confirmed "by design". Dropped the option for version 3.0.0. Still listed in the documentation though.

问题是,当您尝试在具有"compound key"字段上现有重复项的集合上创建索引时,未创建索引并且出错.在上面,索引创建应该在shell中产生:

The problem is that the index is not being created and errors when you attempt to create this on a collection with existing duplicates on the "compound key" fields. On the above, the index creation should yield this in the shell:

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

如果没有重复项,则可以按当前尝试创建索引,索引将被创建.

When there are no duplicates present you can create the index as you are currently trying and it will be created.

要解决此问题,请首先使用以下过程删除重复项:

So to work around this, first remove the duplicates with a procedure like 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 will not be inserted and the appropriate error will be recorded.

这里的最后一点是,"dropDups"不是/不是删除重复数据的非常优雅的解决方案.如上所示,您确实想要具有更多控制权的东西.

The final note here is that "dropDups" is/was not a very elegant solution for removing duplicate data. You really want something with more control as demonstrated above.

对于第二部分,请使用.update()方法,而不要使用.insert().它具有"upsert" 选项

For the second part, rather than use .insert() use the .update() method. It has an "upsert" option

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

因此,找到的"文档被修改",而未找到的文档被插入".另请参见 $setOnInsert 仅在实际插入文档时创建某些数据的方式,而不是在修改时创建的方法.

So the "found" documents are "modified" and the documents not found are "inserted". Also see $setOnInsert for a way to only create certain data when the document is actually inserted and not when modified.

对于您的特定尝试,.update()的正确语法是三个参数. 查询",更新"和选项":

For your specific attempt, the correct syntax of .update() is three arguments. "query", "update" and "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 the update operations are allowed to "access the same path" as used in another update operation in that "update" document section.

这篇关于即使添加了唯一密钥,MongoDB也会复制文档的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆