我有一个用户对象,其中包含用户名,电子邮件地址和版本,每次保存用户时都会递增。将用户保存到Mongo时,更新查询包含版本,如果在保存之前在数据库上修改了用户,则版本将不同,因此不会保存用户。
示例更新查询:
{"username":"name","version":6}
在某些情况下,我想在使用update
保存用户时使用upsert,因为在该阶段可能无法创建其帐户。如果帐户自加载以来已创建和修改,那么根据我的理解,它将尝试创建新文档,因为查询不匹配任何文档。有没有办法只在查询的特定字段不匹配时才创建新文档,例如用户名?
答案 0 :(得分:0)
让我们将用户名设置为' newUser1'以及用户'
的收集在mongo shell中执行以下操作
if(!db.users.findOne({username:newUser1})){db.users.insert({username:newUser1,email:abcnewuser1@gmail.com,version:1})}
注意:我们需要提供准确的用户名
答案 1 :(得分:0)
看起来你的问题陈述就是那个
如果某个其他进程已经更新了您的记录,则代码不应该更新它,因为传递的版本(在内存中)低于数据库中已存在的版本(最近由前一个进程更新)。
但是,如果传递的版本等于已存在最大版本的版本,那么它应该更新。
如果传递的版本严格更大,则应插入记录。
您可以使用以下代码来实现它,但这在生产环境中不是一个非常优雅的解决方案,因为它不会在语句中发生,因此无法保证原子性。对于像环境这样的产品,可能不是很优雅,但你可以根据自己的要求建立它。
--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');
}