如何使用原子操作在一个文档中切换布尔字段



有没有办法用原子操作来切换MongoDB中ONE文档的布尔字段?比如,(在python中)

cl.update({"_id": ...}, {"$toggle": {"field": 1}})

现在,我认为用一个操作不可能做到这一点。按位运算符(http://www.mongodb.org/display/DOCS/Updating#Updating-%24bit)还没有'$xor',尽管我有它的补丁。

现在我想的解决办法是总是使用"$inc":

cl.update({"_id":…},{'$inc':{'field':1}})

然后,你可以检查一个项目是否为"真",而不是检查是真是假:

cl.find({"_id":…,'field':{'$mod':[2,1]})

IE,你可以使用模运算符来判断它是偶数还是不均匀的,偶数是"未设置"的,不均匀是"设置"的。如果你想有opposite行为(即,找到所有没有设置标志的项目),那么使用

[2,0]

SERVER-4362问题现在实际上已经解决,并且$bit更新操作符可用。因此,随着它的xor参数,你现在可以在原子操作中做到这一点:

cl.findOneAndUpdate( 
  { "_id": ...}, 
  { 
     "$bit": { 
         "field": { "xor": NumberInt(1) } 
     } 
  },
  { "returnNewDocument": true, "upsert": true }
);

因此,只要字段的值保持在01,就会产生按位"翻转",使当前值与修改时的值相反。

.findOneAndUpdate()不是必需的,只是证明每次修改的结果值不同的一种方式。

您可以从MongoDB v4.2、开始使用聚合管道的更新

1) 使用$not的选项

  • 计算布尔值并返回相反的布尔值;即当传递评估为true的表达式时,$not返回false;当传递一个计算结果为false的表达式时,$not返回true
cl.update(
  {"_id": ...}, 
  [
    { "$set": { "field": { "$not": "$field" } } }
  ]
)

游乐场

$not的缺点如下:null、0和未定义的值以及其他值为true

2) 使用$eq的选项

  • 若字段为false,则将其设置为true;若字段为任何其他值,则将字段设置为false
cl.update(
  {"_id": ...}, 
  [
    { "$set": { "field": { "$eq": [false, "$field"] } } }
  ]
)

游乐场

最新更新