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

时间:2013-01-25 18:20:30

标签: mongodb pymongo

我有一份文件:

{ '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执行此操作,还是必须按下另一个命令?

2 个答案:

答案 0 :(得分:84)

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

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

因此,这只会针对匹配$push的文档执行_id,并且profile_set元素不在name 'nick' {{1}}

答案 1 :(得分:1)

从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" ]}} 
      }}
   ]}}}
])