【问题标题】:Can you specify a key for $addToSet in Mongo?你可以在 Mongo 中为 $addToSet 指定一个键吗?
【发布时间】: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 会首先运行,您需要两个命令来执行此操作

标签: mongodb pymongo


【解决方案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 中现有对象的后续问题:stackoverflow.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 中询问所有详细信息
猜你喜欢
  • 1970-01-01
  • 2020-03-13
  • 2010-09-22
  • 2014-08-27
  • 2020-08-16
  • 1970-01-01
  • 2010-09-09
  • 1970-01-01
  • 2016-12-21
相关资源
最近更新 更多