gpt4 book ai didi

php - 即使在添加唯一键之后,MongoDB 也会重复文档

转载 作者:IT老高 更新时间:2023-10-28 13:07:59 26 4
gpt4 key购买 nike

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

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

集合看起来像这样“用户服务”

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

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

问题:

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

我想要什么

  1. 在 Mongo Shell 上:在 uid 和 sid 上添加唯一键,并且没有具有相同 uid 和 sid 的重复文档。
  2. 在 PHP 方面:有类似 mysql "insert (value) on duplicate key update rate=rate+1" 的东西。也就是说,每当我尝试插入一个文档时,如果没有,它应该被插入,否则它应该更新文档的 rate 字段

最佳答案

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

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

问题在于,当您尝试在“复合键”字段上存在重复项的集合上创建索引时,未创建索引并且出错。在上面,索引创建应该在 shell 中产生:

{
"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 )
);

不允许任何更新操作“访问与该“更新”文档部分中另一个更新操作中使用的路径相同的路径。

关于php - 即使在添加唯一键之后,MongoDB 也会重复文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29072209/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com