Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.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
Mongodb 使用多个查询条件进行Upsert_Mongodb - Fatal编程技术网

Mongodb 使用多个查询条件进行Upsert

Mongodb 使用多个查询条件进行Upsert,mongodb,Mongodb,我有一个用户对象,其中包含用户名、电子邮件地址和版本,每次保存用户时,该版本都会递增。将用户保存到Mongo时,更新查询包括版本,如果用户在保存之前已在数据库上修改过,则版本将不同,因此不会保存用户 更新查询示例: {“用户名”:“名称”,“版本”:6} 在某些情况下,当我使用update保存用户时,我希望使用upsert,因为在该阶段可能不会创建他们的帐户。如果帐户在加载后已被创建和修改,那么据我所知,它将尝试创建一个新文档,因为查询与任何文档都不匹配。是否有一种方法仅在查询的特定字段不匹配时

我有一个用户对象,其中包含用户名、电子邮件地址和版本,每次保存用户时,该版本都会递增。将用户保存到Mongo时,更新查询包括版本,如果用户在保存之前已在数据库上修改过,则版本将不同,因此不会保存用户

更新查询示例:
{“用户名”:“名称”,“版本”:6}


在某些情况下,当我使用
update
保存用户时,我希望使用upsert,因为在该阶段可能不会创建他们的帐户。如果帐户在加载后已被创建和修改,那么据我所知,它将尝试创建一个新文档,因为查询与任何文档都不匹配。是否有一种方法仅在查询的特定字段不匹配时创建新文档,例如用户名?

让我们将用户名设置为“newUser1”,将集合设置为“users”

在mongoshell中执行以下操作

如果(!db.users.findOne({username:newUser1})){db.users.insert({username:newUser1,电子邮件:abcnewuser1@gmail.com,版本:1})


注意:我们需要提供准确的用户名

看起来您的问题是

  • 如果其他进程已经更新了您的记录,那么代码不应该更新它,因为传递的版本(内存中)低于数据库中已经存在的版本(最近由前一个进程更新)

  • 但是,如果传递的版本等于已存在的max版本,则应进行更新

  • 如果通过的版本严格来说更大,那么它应该插入记录

  • 您可以使用下面的代码来实现它,但这在生产环境中不是一个非常优雅的解决方案,因为它不会发生在语句中,因此原子性不能得到保证。对于类似产品的环境可能不是很优雅,但您可以根据需要在其上构建

    --in the variable userToUpdate, change the version to 0, 1 and 2 to see different types of behaviors as explained in the above 3 points.
    
    db.t1.drop(); //drop if exist
    db.t1.save({uname:"sachin", v:0, email:"email-0"});
    db.t1.save({uname:"sachin", v:1, email:"email-1"});
    //----
    var userToUpdate = {uname:"sachin", v:2, email:"email-2"};
    //----
    var user = userToUpdate.uname;
    var cur = db.t1.find({uname:user}).sort({v:-1}).limit(1);
    var latestVersion = 0;
    if(cur.hasNext()){
        var v1 = cur.next();
        latestVersion = v1['v'];
        printjson('latestVersion='+latestVersion);
    }
    
    versionToUpdate = (userToUpdate.v < latestVersion)? -1 : userToUpdate.v;
    if(versionToUpdate != -1){
      printjson('Going to upsert');
      db.t1.update( {uname:user, v:versionToUpdate}, userToUpdate, {upsert:true} );
    }else{
    printjson('latest version in db : '+latestVersion+', which is greater than the passed    version '+userToUpdate.v+', hence ingoring');
    }
    
    ——在变量userToUpdate中,将版本更改为0、1和2,以查看上述3点中解释的不同类型的行为。
    db.t1.drop()//如果存在,请删除
    db.t1.save({uname:“sachin”,v:0,email:“email-0”});
    db.t1.save({uname:“sachin”,v:1,email:“email-1”});
    //----
    var userToUpdate={uname:“sachin”,v:2,email:“email-2”};
    //----
    var user=userToUpdate.uname;
    var cur=db.t1.find({uname:user}).sort({v:-1}).limit(1);
    var-latestVersion=0;
    if(cur.hasNext()){
    var v1=cur.next();
    最新版本=v1['v'];
    printjson('latestVersion='+latestVersion);
    }
    VersionUpdate=(userToUpdate.v<最新版本)-1:userToUpdate.v;
    如果(版本更新!=-1){
    printjson(“向上插入”);
    update({uname:user,v:versionToUpdate},userToUpdate,{upsert:true});
    }否则{
    printjson('db中的最新版本:'+latestVersion+',大于传递的版本'+userToUpdate.v+',因此为ingoring');
    }
    
    应该允许您这样做。