你可以在 Mongo 中为 $addToSet 指定一个键吗?

Posted

技术标签:

【中文标题】你可以在 Mongo 中为 $addToSet 指定一个键吗?【英文标题】:Can you specify a key for $addToSet in Mongo? 【发布时间】:2013-01-09 18:45:06 【问题描述】:

我有一份文件:

 'profile_set' :
  [
     'name' : 'nick', 'options' : 0 ,
     'name' : 'joe',  'options' : 2 ,
     'name' : 'burt', 'options' : 1 
  ] 

如果名称尚不存在(无论选项如何),并且希望将新文档添加到 profile_set 集中。

所以在这个例子中,如果我尝试添加:

'name' : 'matt', 'options' : 0

它应该添加它,但是添加

'name' : 'nick', 'options' : 2

不应执行任何操作,因为名称为 nick 的文档已经存在,即使 option 不同。

Mongo 似乎与整个元素匹配,我最终检查它是否相同,我最终得到

profile_set containing ['name' : 'nick', 'options' : 0, 'name' : 'nick', 'options' : 2]

有没有办法用$addToSet 做到这一点,还是我必须推送另一个命令?

【问题讨论】:

由于您不能保证 $addToSet 会首先运行,您需要两个命令来执行此操作 【参考方案1】:

如果name 已存在于profile_set 中,您可以使用阻止更新的查询对象限定您的update。在外壳中:

db.coll.update(
    _id: id, 'profile_set.name': $ne: 'nick', 
    $push: profile_set: 'name': 'nick', 'options': 2)

因此,这只会对具有匹配 _id 并且没有 profile_set 元素(其中 name'nick')的文档执行 $push

【讨论】:

如果我以后需要更改 mick 的名称,即更改现有的数组对象,而不是添加新的。有没有办法在一个原子更新操作中仍然遵守名称的唯一约束? 关于更改 profile_set 中现有对象的后续问题:***.com/questions/26590219/…。 无论我去哪里解决 mongoose 或 mongo 问题,@JohnnyHK 总是救了我。 @JohnnyHK 如果我需要覆盖已经存在的值怎么办? 请任何人回复上述@Alex 问题。如果元素已经存在 else 推送,需要更新元素吗?【参考方案2】:

从 MongoDB 4.2 开始,有一种方法可以使用 aggregation expressions in update。

对于您的示例,您可以这样做:

newSubDocs = [ 'name' : 'matt', 'options' : 0, 'name' : 'nick', 'options' : 2 ];
db.coll.update(  _id:1 ,
[ 
   $set:   profile_set:  $concatArrays: [ 
      "$profile_set",  
      $filter: 
             input:newSubDocs, 
             cond: $not: $in: [ "$$this.name", "$profile_set.name" ] 
      
   ]
])

【讨论】:

MongoError: '0.$set' 中的美元 ($) 前缀字段 '$set' 对存储无效。 听起来你没有得到正确的完整语法。您可能想在 community.mongodb.com 中询问所有详细信息

以上是关于你可以在 Mongo 中为 $addToSet 指定一个键吗?的主要内容,如果未能解决你的问题,请参考以下文章

具有多个值的 Mongo $addToSet 语法正确

mongo删除重复行

javascript 在mongo中为终端创建用户

如何在 Python 中为递归对象创建 Mongo 文档模式?

在 MongoDb 中使用 addToSet 时保持原始文档的顺序

如何在 Mongoose 中使用 $addToSet 和 ObjectId 数组?