Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用自定义id值时在mongodb中增加_Mongodb - Fatal编程技术网

使用自定义id值时在mongodb中增加

使用自定义id值时在mongodb中增加,mongodb,Mongodb,如果文档不存在,我需要插入一个文档。我知道“upsert”选项可以做到这一点,但我有一些特殊的需要 首先,我只需要创建带有_id字段的文档,但前提是它还不存在。My _id字段是我生成的数字(不是ObjectId)。如果我使用“upsert”选项,那么我会得到“Mod on\u id not allowed” 我知道我们不能在$set中使用_id 所以,我的问题是:在mongodb中是否有任何方法可以原子化地“创建如果不存在的话”呢 编辑: 根据@Barrie的建议,本工程(使用nodejs和m

如果文档不存在,我需要插入一个文档。我知道“upsert”选项可以做到这一点,但我有一些特殊的需要

首先,我只需要创建带有_id字段的文档,但前提是它还不存在。My _id字段是我生成的数字(不是ObjectId)。如果我使用“upsert”选项,那么我会得到“Mod on\u id not allowed”

我知道我们不能在$set中使用_id

所以,我的问题是:在mongodb中是否有任何方法可以原子化地“创建如果不存在的话”呢

编辑: 根据@Barrie的建议,本工程(使用nodejs和mongoose):


但是我仍然怀疑这是否是最好的方法。

您可以使用insert()。如果您指定的id为的文档已经存在,则insert()将失败,不会修改任何内容-因此,当您将insert()与用户创建的id一起使用时,“如果它不存在则创建”是默认情况下它已经在做的事情。

我也遇到了同样的问题,但找到了更好的解决方案。如果只需从更新对象中删除_id属性,就可以使用相同的查询样式。因此,如果一开始你发现这个错误:

db.mycollection.update({ _id: id }, {$set: { _id: id, name: 'name' }}, { upsert: true });
相反,请使用以下命令:

db.mycollection.update({ _id: id }, {$set: { name: 'name' }}, { upsert: true });

这更好,因为它同时适用于插入和更新。

更新:可以在不使用
$setOnInsert
的情况下使用_id进行Upsert,如上@Barrie所述

诀窍是将
$setOnInsert:{u id:1}
与upsert一起使用,这样{u id仅在插入时写入,而不用于更新

-我刚在2.4上试过,但不起作用


我使用的解决方法是使用另一个具有唯一索引的ID字段。例如,
$setOnInsert:{myId:1}

请注意,当您向上插入一个简单的key=>value对象(不是$set或其他对象)时,$setOnInsert不容易工作。 我需要使用它(在PHP中):


是否尝试使用
保存操作?i、 e.db.collection.save({“\u id”:您的\u id})保存失败,如果已经存在,则会出现重复键错误。如问题中所述,是否使用非ObjectID的\u id执行此操作?是。它会导致错误
Mod on _idnot allowed
,将_id作为ObjectID或自定义值。因此,您必须始终从
$set
对象中删除_id。@natebar:效果很好!谢谢:)但是如果我使用shortid生成,并且这种类型的upsert将从mongo创建一个id,那么会发生什么呢?如果您习惯使用shortid,这将是一个问题。这仍然不能处理在插入之后和后续更新之前删除文档的竞争条件。setOnInsert对我有效。而巴里的回答,直接插入不会做更新工作;内特·巴尔(Nate Barr)的回答“由id更新”限制了查找标准。我想做的是:db.coll.update({a:1,b:2},{$set:{c:3,d:4},$setOnInsert:{u id:'xxxx'},{upsert:true})
db.mycollection.update({ _id: id }, {$set: { _id: id, name: 'name' }}, { upsert: true });
db.mycollection.update({ _id: id }, {$set: { name: 'name' }}, { upsert: true });
public function update($criteria , $new_object, array $options = array()){
    // In 2.6, $setOnInsert with upsert == true work with _id field
    if(isset($options['upsert']) && $options['upsert']){
        $firstKey = array_keys($new_object)[0];
        if(strpos($firstKey, '$')===0){
            $new_object['$setOnInsert']['_id'] = $this->getStringId();
        }
        //Even, we need to check if the object exists
        else if($this->findOne($criteria, ['_id'])===null){
            //In this case, we need to set the _id
            $new_object['_id'] = $this->getStringId();
        }

    }
    return parent::update($criteria, $new_object, $options);
}