使用多个查询条件进行升级

时间:2015-06-25 05:46:58

标签: mongodb

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

示例更新查询: {"username":"name","version":6}

在某些情况下,我想在使用update保存用户时使用upsert,因为在该阶段可能无法创建其帐户。如果帐户自加载以来已创建和修改,那么根据我的理解,它将尝试创建新文档,因为查询不匹配任何文档。有没有办法只在查询的特定字段不匹配时才创建新文档,例如用户名?

2 个答案:

答案 0 :(得分:0)

让我们将用户名设置为' newUser1'以及用户'

的收集

在mongo shell中执行以下操作

if(!db.users.findOne({username:newUser1})){db.users.insert({username:newUser1,email:abcnewuser1@gmail.com,version:1})}

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

答案 1 :(得分:0)

看起来你的问题陈述就是那个

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

  2. 但是,如果传递的版本等于已存在最大版本的版本,那么它应该更新。

  3. 如果传递的版本严格更大,则应插入记录。

  4. 您可以使用以下代码来实现它,但这在生产环境中不是一个非常优雅的解决方案,因为它不会在语句中发生,因此无法保证原子性。对于像环境这样的产品,可能不是很优雅,但你可以根据自己的要求建立它。

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