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

nic*_*ine 64 mongodb pymongo

我有一份文件:

{ 'profile_set' :
  [
    { 'name' : 'nick', 'options' : 0 },
    { 'name' : 'joe',  'options' : 2 },
    { 'name' : 'burt', 'options' : 1 }
  ] 
}
Run Code Online (Sandbox Code Playgroud)

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

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

{'name' : 'matt', 'options' : 0}

它应该添加它,但添加

{'name' : 'nick', 'options' : 2}

应该什么也不做,因为文件已经存在,nick即使名称option不同.

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

profile_set containing [{'name' : 'nick', 'options' : 0}, {'name' : 'nick', 'options' : 2}]
Run Code Online (Sandbox Code Playgroud)

有没有办法用$ addToSet执行此操作,还是我必须推送另一个命令?

Joh*_*yHK 86

您可以update使用查询对象限定您的查询对象,如果name已存在,则阻止更新profile_set.在shell中:

db.coll.update(
    {_id: id, 'profile_set.name': {$ne: 'nick'}}, 
    {$push: {profile_set: {'name': 'nick', 'options': 2}}})
Run Code Online (Sandbox Code Playgroud)

因此,这将只执行$push与匹配一个文档_id和那里没有一个profile_set地方元素name'nick'.

  • @JohnnyHK如果我需要覆盖该值,该怎么办? (5认同)
  • 无论我去哪里解决猫鼬或蒙哥的问题,@约翰尼总是救了我. (3认同)
  • 请任何人回复上面的@Alex 问题。如果元素已经存在,还需要什么来更新元素? (3认同)

Asy*_*sky 7

从 MongoDB 4.2 开始,有一种方法可以使用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" ]}} 
      }}
   ]}}}
])
Run Code Online (Sandbox Code Playgroud)